From 74aa2ad3128387099dfc832ebf8da15677611264 Mon Sep 17 00:00:00 2001 From: Ethan Konkolowicz Date: Fri, 13 Feb 2026 16:49:47 -0500 Subject: [PATCH 1/3] added generic client type that only requires specifc methods from our clients, that way version bumps are cross compatible --- .changeset/lucky-pens-send.md | 5 ++ packages/viem/package.json | 1 + packages/viem/src/index.ts | 144 ++++++++++++++++++++-------------- pnpm-lock.yaml | 3 + 4 files changed, 95 insertions(+), 58 deletions(-) create mode 100644 .changeset/lucky-pens-send.md diff --git a/.changeset/lucky-pens-send.md b/.changeset/lucky-pens-send.md new file mode 100644 index 000000000..d9c975a13 --- /dev/null +++ b/.changeset/lucky-pens-send.md @@ -0,0 +1,5 @@ +--- +"@turnkey/viem": patch +--- + +Replaced concrete client types with a generic method-based interface to avoid type errors and make client types version-agnostic. diff --git a/packages/viem/package.json b/packages/viem/package.json index 7867aada6..5bb237aff 100644 --- a/packages/viem/package.json +++ b/packages/viem/package.json @@ -63,6 +63,7 @@ "@turnkey/sdk-browser": "workspace:*", "@turnkey/sdk-server": "workspace:*", "@turnkey/core": "workspace:*", + "@turnkey/sdk-types": "workspace:*", "cross-fetch": "^4.0.0" }, "devDependencies": { diff --git a/packages/viem/src/index.ts b/packages/viem/src/index.ts index 12421b33e..eedd6f616 100644 --- a/packages/viem/src/index.ts +++ b/packages/viem/src/index.ts @@ -35,11 +35,77 @@ import { TurnkeyActivityConsensusNeededError as TurnkeyHttpActivityConsensusNeededError, TurnkeyClient, type TurnkeyApiTypes, + type TurnkeyApi as HttpApiTypes, } from "@turnkey/http"; import { ApiKeyStamper } from "@turnkey/api-key-stamper"; -import type { TurnkeyBrowserClient } from "@turnkey/sdk-browser"; -import type { TurnkeySDKClientBase } from "@turnkey/core"; -import type { TurnkeyServerClient } from "@turnkey/sdk-server"; +import type { TurnkeySDKApiTypes as BrowserApiTypes } from "@turnkey/sdk-browser"; +import type { TurnkeySDKApiTypes as ServerApiTypes } from "@turnkey/sdk-server"; +import type { + TGetPrivateKeyBody as SdkTypesGetPrivateKeyBody, + TGetPrivateKeyResponse as SdkTypesGetPrivateKeyResponse, + TSignTransactionBody as SdkTypesSignTransactionBody, + TSignTransactionResponse as SdkTypesSignTransactionResponse, + TSignRawPayloadBody as SdkTypesSignRawPayloadBody, + TSignRawPayloadResponse as SdkTypesSignRawPayloadResponse, +} from "@turnkey/sdk-types"; + +/** + * Union types that accept inputs/outputs from any SDK package. + * All SDK packages generate these from the same OpenAPI spec, so they're structurally identical. + */ +export type TGetPrivateKeyBody = + | BrowserApiTypes.TGetPrivateKeyBody + | ServerApiTypes.TGetPrivateKeyBody + | SdkTypesGetPrivateKeyBody + | HttpApiTypes.TGetPrivateKeyBody; + +export type TGetPrivateKeyResponse = + | BrowserApiTypes.TGetPrivateKeyResponse + | ServerApiTypes.TGetPrivateKeyResponse + | SdkTypesGetPrivateKeyResponse + | HttpApiTypes.TGetPrivateKeyResponse; + +export type TSignTransactionBody = + | BrowserApiTypes.TSignTransactionBody + | ServerApiTypes.TSignTransactionBody + | SdkTypesSignTransactionBody + | HttpApiTypes.TSignTransactionBody; + +export type TSignTransactionResponse = + | BrowserApiTypes.TSignTransactionResponse + | ServerApiTypes.TSignTransactionResponse + | SdkTypesSignTransactionResponse + | HttpApiTypes.TSignTransactionResponse; + +export type TSignRawPayloadBody = + | BrowserApiTypes.TSignRawPayloadBody + | ServerApiTypes.TSignRawPayloadBody + | SdkTypesSignRawPayloadBody + | HttpApiTypes.TSignRawPayloadBody; + +export type TSignRawPayloadResponse = + | BrowserApiTypes.TSignRawPayloadResponse + | ServerApiTypes.TSignRawPayloadResponse + | SdkTypesSignRawPayloadResponse + | HttpApiTypes.TSignRawPayloadResponse; + +/** + * Minimal interface for Turnkey SDK clients (browser, server, core, etc.). + * Uses union types that accept inputs/outputs from any SDK package. + */ +export interface TurnkeySDKClientInterface { + getPrivateKey(input: TGetPrivateKeyBody): Promise; + signTransaction( + input: TSignTransactionBody, + ): Promise; + signRawPayload(input: TSignRawPayloadBody): Promise; +} + +/** + * Union type for all supported Turnkey client types. + * TurnkeyClient is the HTTP client, TurnkeySDKClientInterface covers other SDK clients. + */ +export type TTurnkeyClient = TurnkeySDKClientInterface; export type TTurnkeyConsensusNeededErrorType = TurnkeyConsensusNeededError & { name: "TurnkeyConsensusNeededError"; @@ -124,11 +190,7 @@ export class TurnkeyActivityError extends BaseError { } export function createAccountWithAddress(input: { - client: - | TurnkeyClient - | TurnkeyBrowserClient - | TurnkeyServerClient - | TurnkeySDKClientBase; + client: TTurnkeyClient; organizationId: string; // This can be a wallet account address, private key address, or private key ID. signWith: string; @@ -202,11 +264,7 @@ export function createAccountWithAddress(input: { } export async function createAccount(input: { - client: - | TurnkeyClient - | TurnkeyBrowserClient - | TurnkeyServerClient - | TurnkeySDKClientBase; + client: TTurnkeyClient; organizationId: string; // This can be a wallet account address, private key address, or private key ID. signWith: string; @@ -371,11 +429,7 @@ export async function createApiKeyAccount( } export async function signAuthorization( - client: - | TurnkeyClient - | TurnkeyBrowserClient - | TurnkeyServerClient - | TurnkeySDKClientBase, + client: TTurnkeyClient, parameters: TSignAuthorizationParameters, organizationId: string, signWith: string, @@ -417,11 +471,7 @@ export async function signAuthorization( } export async function signMessage( - client: - | TurnkeyClient - | TurnkeyBrowserClient - | TurnkeyServerClient - | TurnkeySDKClientBase, + client: TTurnkeyClient, message: SignableMessage, organizationId: string, signWith: string, @@ -438,11 +488,7 @@ export async function signMessage( export async function signTransaction< TTransactionSerializable extends TransactionSerializable, >( - client: - | TurnkeyClient - | TurnkeyBrowserClient - | TurnkeyServerClient - | TurnkeySDKClientBase, + client: TTurnkeyClient, transaction: TTransactionSerializable, serializer: SerializeTransactionFn, organizationId: string, @@ -485,11 +531,7 @@ export async function signTransaction< } export async function signTypedData( - client: - | TurnkeyClient - | TurnkeyBrowserClient - | TurnkeyServerClient - | TurnkeySDKClientBase, + client: TTurnkeyClient, data: TypedData | { [key: string]: unknown }, organizationId: string, signWith: string, @@ -505,11 +547,7 @@ export async function signTypedData( } async function signTransactionWithErrorWrapping( - client: - | TurnkeyClient - | TurnkeyBrowserClient - | TurnkeyServerClient - | TurnkeySDKClientBase, + client: TTurnkeyClient, unsignedTransaction: string, organizationId: string, signWith: string, @@ -551,11 +589,7 @@ async function signTransactionWithErrorWrapping( } async function signTransactionImpl( - client: - | TurnkeyClient - | TurnkeyBrowserClient - | TurnkeyServerClient - | TurnkeySDKClientBase, + client: TTurnkeyClient, unsignedTransaction: string, organizationId: string, signWith: string, @@ -579,7 +613,7 @@ async function signTransactionImpl( activity?.result?.signTransactionResult?.signedTransaction, ); } else { - const { activity, signedTransaction } = await client.signTransaction({ + const { activity } = await client.signTransaction({ organizationId, signWith, type: transactionType ?? "TRANSACTION_TYPE_ETHEREUM", @@ -590,16 +624,14 @@ async function signTransactionImpl( activity as any /* Type casting is ok here. The invalid types are both actually strings. TS is too strict here! */, ); + const signedTransaction = + activity.result.signTransactionResult?.signedTransaction; return assertNonNull(signedTransaction); } } async function signMessageWithErrorWrapping( - client: - | TurnkeyClient - | TurnkeyBrowserClient - | TurnkeyServerClient - | TurnkeySDKClientBase, + client: TTurnkeyClient, message: string, organizationId: string, signWith: string, @@ -644,11 +676,7 @@ async function signMessageWithErrorWrapping( } async function signMessageImpl( - client: - | TurnkeyClient - | TurnkeyBrowserClient - | TurnkeyServerClient - | TurnkeySDKClientBase, + client: TTurnkeyClient, message: string, organizationId: string, signWith: string, @@ -674,7 +702,7 @@ async function signMessageImpl( result = assertNonNull(activity?.result?.signRawPayloadResult); } else { - const { activity, r, s, v } = await client.signRawPayload({ + const { activity } = await client.signRawPayload({ organizationId, signWith, payload: message, @@ -687,9 +715,9 @@ async function signMessageImpl( ); result = { - r, - s, - v, + r: assertNonNull(activity?.result?.signRawPayloadResult?.r), + s: assertNonNull(activity?.result?.signRawPayloadResult?.s), + v: assertNonNull(activity?.result?.signRawPayloadResult?.v), }; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 95d60694c..6204f8a8a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -3855,6 +3855,9 @@ importers: '@turnkey/sdk-server': specifier: workspace:* version: link:../sdk-server + '@turnkey/sdk-types': + specifier: workspace:* + version: link:../sdk-types cross-fetch: specifier: ^4.0.0 version: 4.0.0(encoding@0.1.13) From 129cfe8a30f6a61087dc49b56204ee0906ac5a3b Mon Sep 17 00:00:00 2001 From: Ethan Konkolowicz Date: Fri, 20 Feb 2026 12:53:15 -0500 Subject: [PATCH 2/3] made change a minor bump rather than a patch just in case --- .changeset/lucky-pens-send.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/lucky-pens-send.md b/.changeset/lucky-pens-send.md index d9c975a13..926e00fb1 100644 --- a/.changeset/lucky-pens-send.md +++ b/.changeset/lucky-pens-send.md @@ -1,5 +1,5 @@ --- -"@turnkey/viem": patch +"@turnkey/viem": minor --- Replaced concrete client types with a generic method-based interface to avoid type errors and make client types version-agnostic. From b146a06327135c1a51276b0c0a969a58b6904ea6 Mon Sep 17 00:00:00 2001 From: Ethan Konkolowicz Date: Fri, 20 Feb 2026 14:14:51 -0500 Subject: [PATCH 3/3] made generic response types even looser --- packages/viem/src/index.ts | 69 +++++++++++++++++++++----------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/packages/viem/src/index.ts b/packages/viem/src/index.ts index eedd6f616..c3c656363 100644 --- a/packages/viem/src/index.ts +++ b/packages/viem/src/index.ts @@ -42,16 +42,12 @@ import type { TurnkeySDKApiTypes as BrowserApiTypes } from "@turnkey/sdk-browser import type { TurnkeySDKApiTypes as ServerApiTypes } from "@turnkey/sdk-server"; import type { TGetPrivateKeyBody as SdkTypesGetPrivateKeyBody, - TGetPrivateKeyResponse as SdkTypesGetPrivateKeyResponse, TSignTransactionBody as SdkTypesSignTransactionBody, - TSignTransactionResponse as SdkTypesSignTransactionResponse, TSignRawPayloadBody as SdkTypesSignRawPayloadBody, - TSignRawPayloadResponse as SdkTypesSignRawPayloadResponse, } from "@turnkey/sdk-types"; /** - * Union types that accept inputs/outputs from any SDK package. - * All SDK packages generate these from the same OpenAPI spec, so they're structurally identical. + * Union types for inputs — accept the body format from any SDK package. */ export type TGetPrivateKeyBody = | BrowserApiTypes.TGetPrivateKeyBody @@ -59,41 +55,58 @@ export type TGetPrivateKeyBody = | SdkTypesGetPrivateKeyBody | HttpApiTypes.TGetPrivateKeyBody; -export type TGetPrivateKeyResponse = - | BrowserApiTypes.TGetPrivateKeyResponse - | ServerApiTypes.TGetPrivateKeyResponse - | SdkTypesGetPrivateKeyResponse - | HttpApiTypes.TGetPrivateKeyResponse; - export type TSignTransactionBody = | BrowserApiTypes.TSignTransactionBody | ServerApiTypes.TSignTransactionBody | SdkTypesSignTransactionBody | HttpApiTypes.TSignTransactionBody; -export type TSignTransactionResponse = - | BrowserApiTypes.TSignTransactionResponse - | ServerApiTypes.TSignTransactionResponse - | SdkTypesSignTransactionResponse - | HttpApiTypes.TSignTransactionResponse; - export type TSignRawPayloadBody = | BrowserApiTypes.TSignRawPayloadBody | ServerApiTypes.TSignRawPayloadBody | SdkTypesSignRawPayloadBody | HttpApiTypes.TSignRawPayloadBody; -export type TSignRawPayloadResponse = - | BrowserApiTypes.TSignRawPayloadResponse - | ServerApiTypes.TSignRawPayloadResponse - | SdkTypesSignRawPayloadResponse - | HttpApiTypes.TSignRawPayloadResponse; +/** + * Minimal response types — only the fields the viem package actually reads. + * This makes responses version-agnostic; any SDK version will satisfy these. + */ +type TGetPrivateKeyResponse = { + privateKey: { + addresses: Array<{ format?: string; address?: string }>; + }; +}; + +type TSignTransactionResponse = { + activity: { + id: string; + status: string; + result: { + signTransactionResult?: { + signedTransaction?: string; + }; + }; + }; +}; + +type TSignRawPayloadResponse = { + activity: { + id: string; + status: string; + result: { + signRawPayloadResult?: { + r?: string; + s?: string; + v?: string; + }; + }; + }; +}; /** - * Minimal interface for Turnkey SDK clients (browser, server, core, etc.). - * Uses union types that accept inputs/outputs from any SDK package. + * Generic client interface for any Turnkey client (HTTP, browser SDK, server SDK, core, etc.). */ -export interface TurnkeySDKClientInterface { +export interface TurnkeyClientInterface { getPrivateKey(input: TGetPrivateKeyBody): Promise; signTransaction( input: TSignTransactionBody, @@ -101,11 +114,7 @@ export interface TurnkeySDKClientInterface { signRawPayload(input: TSignRawPayloadBody): Promise; } -/** - * Union type for all supported Turnkey client types. - * TurnkeyClient is the HTTP client, TurnkeySDKClientInterface covers other SDK clients. - */ -export type TTurnkeyClient = TurnkeySDKClientInterface; +export type TTurnkeyClient = TurnkeyClientInterface; export type TTurnkeyConsensusNeededErrorType = TurnkeyConsensusNeededError & { name: "TurnkeyConsensusNeededError";