diff --git a/docs/docs.json b/docs/docs.json index fa5be3419..8d04f3bc2 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -153,6 +153,7 @@ { "group": "Guides", "pages": [ + "guides/v7-to-v8-migration", "guides/lit-action-sign-as-action", "guides/server-sessions" ] @@ -246,4 +247,4 @@ "discord": "https://litgateway.com/discord" } } -} \ No newline at end of file +} diff --git a/docs/guides/v7-to-v8-migration.mdx b/docs/guides/v7-to-v8-migration.mdx new file mode 100644 index 000000000..9b05e56a3 --- /dev/null +++ b/docs/guides/v7-to-v8-migration.mdx @@ -0,0 +1,562 @@ +--- +title: "Migrating from Lit SDK v7 (Datil) to v8 (Naga)" +description: "Complete migration guide covering package renames, authContext, Lit Actions runtime changes, PKP signing, encryption, wrapped keys, and the new payment system." +--- + +# Overview + +Lit SDK v8 (“Naga”) is a major release over v7 (“Datil”). The public API is more modular, uses `viem` for chain interactions, introduces the `AuthManager`/`authContext` model, and replaces Capacity Credits with Ledger‑based payments. + +This guide is written for teams upgrading existing v7 integrations. It focuses on **breaking changes** and **exact replacements**. + +# Upgrade checklist + +1. Replace v7 packages/imports with v8 packages (see tables below). +2. Swap `LitNodeClient`/`connect()` for `createLitClient()`. +3. Replace `sessionSigs` and most `authSig` usage with `authContext` from `AuthManager` (`authSig` remains optional only for `decrypt` overrides). +4. Update Lit Actions to read inputs from `jsParams.*` (no longer global). +5. Update PKP signing to `litClient.chain.*.pkpSign`. +6. Replace v7 encryption helpers with `litClient.encrypt` / `litClient.decrypt`. +7. If you use Wrapped Keys, keep using `pkpSessionSigs` but mint them via `AuthManager`. +8. On paid networks, migrate Capacity Credits flows to the new `PaymentManager`. + +# Quick reference: v7 → v8 mapping + +Use this section as a **searchable symbol map**. Find the v7 name you used and jump to the v8 equivalent. + +## Packages and modules + +| v7 | v8 | Notes | +| --- | --- | --- | +| `@lit-protocol/lit-node-client` | `@lit-protocol/lit-client` | Core client package renamed/re‑architected. | +| `@lit-protocol/lit-node-client-nodejs` | **Removed** | v8 is isomorphic; use `@lit-protocol/lit-client` in Node and browser. | +| `@lit-protocol/lit-auth-client` | `@lit-protocol/auth` (+ optional `@lit-protocol/auth-services`) | Providers replaced by authenticators + AuthManager; hosted infra moved to auth-services. | +| `@lit-protocol/pkp-*` (ethers/cosmos/sui/walletconnect/…) | **Removed** | Use `litClient.getPkpViemAccount()` or `litClient.chain.*.pkpSign`. | +| `@lit-protocol/encryption` | **Removed from core flow** | Use `litClient.encrypt` / `litClient.decrypt`. | +| `@lit-protocol/contracts-sdk` | `@lit-protocol/contracts` | Contract helpers updated for Naga networks. | +| `LIT_NETWORK.*` constants | network modules from `@lit-protocol/networks` | Example: `nagaDev`, `nagaTest`. | + +## Client + network setup + +| v7 | v8 | Notes | +| --- | --- | --- | +| `new LitNodeClient({ litNetwork, debug, ... })` | `await createLitClient({ network })` | Handshake happens during creation. | +| `litNodeClient.connect()` | **Removed** | No explicit connect step in v8. | +| `litNodeClient.disconnect()` | `litClient.disconnect()` | Stops state manager/handshake polling. | +| `litNodeClient.getLatestBlockhash()` | `const { latestBlockhash } = await litClient.getContext()` | Mostly internal now; AuthManager handles nonces. | +| `litNodeClient.signSessionKey()` | **Don’t call directly** | Still exists as a low‑level endpoint; AuthManager uses it. | +| `rpcUrl / bootstrapUrls` in client config | `network.withOverrides({ rpcUrl })` | Overrides are applied on the network module. | + +## Networks + +| v7 network | v8 network module | Notes | +| --- | --- | --- | +| `datil-dev` / `LIT_NETWORK.DatilDev` | `nagaDev` | Free dev network. | +| `datil-test` / `LIT_NETWORK.DatilTest` | `nagaTest` | Paid testnet with Ledger. | +| `datil` / `LIT_NETWORK.Datil` | `naga` | Mainnet module (still rolling out). | + +## Authentication and session material + +| v7 | v8 | Notes | +| --- | --- | --- | +| `authSig` required params on core APIs | **Removed** (optional on `decrypt`) | Core APIs accept `authContext`; `decrypt` also allows an optional `authSig` override. | +| `sessionSigs` params on core APIs | **Removed** | Session sigs minted internally from authContext. | +| `litNodeClient.getSessionSigs(...)` | `authManager.createEoaAuthContext(...)` | No `authNeededCallback` required. | +| `litNodeClient.getPkpSessionSigs(...)` | `authManager.createPkpAuthContext(...)` (core) or `authManager.createPkpSessionSigs(...)` (wrapped‑keys) | Wrapped‑keys still needs exported sigs. | +| `litNodeClient.getLitActionSessionSigs(...)` | `authManager.createCustomAuthContext(...)` or `createEoaAuthContext` with `lit-action-execution` | Depends on whether a Lit Action is your auth method. | +| `resourceAbilityRequests: [{ resource, ability }]` | `resources: [[litAbility, "*"]]` | Example: `[['lit-action-execution','*']]`. | +| `generateSessionCapabilityObjectWithWildcards(...)` on client | `generateSessionCapabilityObjectWithWildcards(...)` from `@lit-protocol/auth-helpers` | Same helper, now standalone. | + +## Core APIs + +| v7 call | v8 call | Notes | +| --- | --- | --- | +| `litNodeClient.executeJs({ sessionSigs, code/ipfsId, jsParams })` | `litClient.executeJs({ authContext, code/ipfsId, jsParams })` | `jsParams` is nested in actions (see below). | +| `litNodeClient.pkpSign({ sessionSigs, pubKey, toSign })` | `litClient.chain.ethereum.pkpSign({ authContext, pubKey, toSign })` | Use `chain.bitcoin` or `chain.raw` for other schemes. | +| `encryptString(...)` / `encryptUint8Array(...)` (`@lit-protocol/encryption`) | `litClient.encrypt({ dataToEncrypt, unifiedAccessControlConditions, chain })` | Encryption does **not** require authContext. | +| `decryptToString(...)` / `decryptToUint8Array(...)` (`@lit-protocol/encryption`) | `litClient.decrypt({ data, unifiedAccessControlConditions, authContext, chain })` | Decryption **requires** authContext. | +| `getHashedAccessControlConditions(...)` on client | `getHashedAccessControlConditions(...)` from `@lit-protocol/access-control-conditions` | Same name, standalone. | +| `getFormattedAccessControlConditions(...)` on client | `getFormattedAccessControlConditions(...)` from `@lit-protocol/access-control-conditions` | Same name, standalone. | +| `litNodeClient.getSignedToken(...)` (JWT) | **Not yet ported / undocumented** | No v8 public helper at time of writing. | + +## Lit Actions runtime + +| v7 Lit Action | v8 Lit Action | Notes | +| --- | --- | --- | +| Globals injected from `jsParams` | Access via `jsParams.*` | Example: `magicNumber` → `jsParams.magicNumber`. | +| `LitActions.*` | `Lit.Actions.*` | New canonical namespace. | + +## PKP management & permissions + +| v7 | v8 | Notes | +| --- | --- | --- | +| `new LitContracts(...)` (`@lit-protocol/contracts-sdk`) | `litClient.mintWithEoa` / `litClient.mintWithAuth` | PKP minting moved onto litClient. | +| `contractsClient.addPermittedAction(...)` | `pkpPermissionsManager.addPermittedAction(...)` | Obtain manager via `litClient.getPKPPermissionsManager`. | +| `contractsClient.addPermittedAddress(...)` | `pkpPermissionsManager.addPermittedAddress(...)` | Same method name, new object. | +| `contractsClient.addPermittedAuthMethod(...)` | `pkpPermissionsManager.addPermittedAuthMethod(...)` | Same name, new object. | +| `contractsClient.getPermittedActions/Addresses/AuthMethods` | `pkpPermissionsManager.getPermittedActions/Addresses/AuthMethods` | Same names. | +| `provider.fetchPKPs(...)` / `provider.getPKPsForAuthMethod(authMethod)` (`@lit-protocol/lit-auth-client`) | `litClient.viewPKPsByAddress({ ownerAddress })` / `litClient.viewPKPsByAuthData({ authData })` | PKP discovery moved onto litClient. | + +## Wrapped Keys + +| v7 | v8 | Notes | +| --- | --- | --- | +| `wrappedKeysApi.*({ pkpSessionSigs, litNodeClient })` | `wrappedKeysApi.*({ pkpSessionSigs, litClient })` | Only the client param changes. | +| `litNodeClient.getPkpSessionSigs` for WK | `authManager.createPkpSessionSigs` | Generate via AuthManager + delegation auth sig. | + +## Payments + +| v7 | v8 | Notes | +| --- | --- | --- | +| Capacity Credits NFTs | **Removed** | Paid networks use Ledger balance per request. | +| `createCapacityDelegationAuthSig` | `paymentManager.delegatePaymentsBatch` | Sponsoring users now uses payment delegation. | +| Capacity “request per kilosecond” limits | `paymentManager.setRestriction` | Same concept, new API. | + +# Package and import changes + +## Core client + networks + +| v7 | v8 | +| --- | --- | +| `@lit-protocol/lit-node-client` | `@lit-protocol/lit-client` | +| `@lit-protocol/lit-node-client-nodejs` | **Removed** (use `@lit-protocol/lit-client` everywhere) | +| `LIT_NETWORK.*` from `@lit-protocol/constants` | network modules from `@lit-protocol/networks` | +| `@lit-protocol/encryption` helpers | **Removed from core flow** → use `litClient.encrypt` / `litClient.decrypt` | + +Install: + +```bash +npm i @lit-protocol/lit-client @lit-protocol/networks viem +``` + +`viem` is a peer dependency in v8; your app must install it. + +## Authentication + +| v7 | v8 | +| --- | --- | +| `litNodeClient.getSessionSigs()` | `authManager.createEoaAuthContext()` | +| `litNodeClient.getPkpSessionSigs()` | `authManager.createPkpSessionSigs()` (for wrapped-keys) or `authManager.createPkpAuthContext()` (for core APIs) | +| `@lit-protocol/lit-auth-client` providers (e.g. `EthWalletProvider`) | `@lit-protocol/auth` authenticators + `AuthManager` | +| Hosted login/mint infra via v7 clients | `@lit-protocol/auth-services` (optional infra) | + +Install: + +```bash +npm i @lit-protocol/auth viem +``` + +## PKP wallets / chain libs + +| v7 | v8 | +| --- | --- | +| `@lit-protocol/pkp-ethers`, `PKPEthersWallet`, etc. | **Removed** → use `litClient.getPkpViemAccount()` or `litClient.chain.*.pkpSign` | +| `ethers`-first examples | `viem`-first examples | + +## Contracts + +| v7 | v8 | +| --- | --- | +| `@lit-protocol/contracts-sdk` | `@lit-protocol/contracts` | + +# Networks and client setup + +## v7 + +```ts +import { LitNodeClient } from "@lit-protocol/lit-node-client"; +import { LIT_NETWORK } from "@lit-protocol/constants"; + +const litNodeClient = new LitNodeClient({ + litNetwork: LIT_NETWORK.DatilDev, + debug: false, +}); +await litNodeClient.connect(); +``` + +## v8 + +```ts +import { createLitClient } from "@lit-protocol/lit-client"; +import { nagaDev } from "@lit-protocol/networks"; + +const litClient = await createLitClient({ network: nagaDev }); +// optional when shutting down: +litClient.disconnect(); +``` + + + If you previously used `litNodeClient.getLatestBlockhash()` (for SIWE nonces), + you can access it via `const { latestBlockhash } = await litClient.getContext();`. + + +### Network name mapping + +| v7 network | v8 network | +| --- | --- | +| `datil-dev` / `LIT_NETWORK.DatilDev` | `naga-dev` / `nagaDev` | +| `datil-test` / `LIT_NETWORK.DatilTest` | `naga-test` / `nagaTest` | +| `datil` / `LIT_NETWORK.Datil` | `naga` / `naga` (mainnet coming soon) | + +### Custom RPC / bootstrap overrides + +v7 typically passed `rpcUrl` or custom bootstrap URLs into the client config. +v8 does this on the **network module**: + +```ts +import { nagaTest } from "@lit-protocol/networks"; + +const network = nagaTest.withOverrides({ + rpcUrl: "https://my-private-rpc.example.com", +}); + +const litClient = await createLitClient({ network }); +``` + +# Authentication and sessions + +v8 removes `sessionSigs` from core APIs and no longer requires `authSig` (except as an optional override on `decrypt`). Instead, you create an `authContext` once and pass it to any method that needs authorization. + +## EOA session (replaces `getSessionSigs`) + +### v7 + +```ts +const sessionSigs = await litNodeClient.getSessionSigs({ + chain: "ethereum", + expiration: new Date(Date.now() + 10 * 60 * 1000).toISOString(), + resourceAbilityRequests: [ + { resource: new LitActionResource("*"), ability: LIT_ABILITY.LitActionExecution }, + ], + authNeededCallback: async ({ uri, expiration, resourceAbilityRequests }) => { + const toSign = await createSiweMessage({ + uri, + expiration, + resources: resourceAbilityRequests, + walletAddress: await ethersWallet.getAddress(), + nonce: await litNodeClient.getLatestBlockhash(), + litNodeClient, + }); + return generateAuthSig({ signer: ethersWallet, toSign }); + }, +}); +``` + +### v8 + +```ts +import { createAuthManager, storagePlugins } from "@lit-protocol/auth"; + +const authManager = createAuthManager({ + storage: storagePlugins.localStorage({ + appName: "my-app", + networkName: "naga-dev", + }), +}); + +const eoaAuthContext = await authManager.createEoaAuthContext({ + config: { account: myViemAccount }, + authConfig: { + domain: "example.com", + statement: "Authorize Lit session", + resources: [ + ["lit-action-execution", "*"], + ["access-control-condition-decryption", "*"], + ["pkp-signing", "*"], + ], + expiration: new Date(Date.now() + 15 * 60 * 1000).toISOString(), + }, + litClient, +}); +``` + +You no longer build SIWE messages or fetch nonces manually; the AuthManager handles that through its authenticators. + + + v7 helpers like `checkAndSignAuthMessage` / `signAndSaveAuthMessage` are no longer needed. + AuthManager persists session materials automatically using the storage plugin you configure. + + +## PKP session (core APIs) + +### v7 + +You typically generated `pkpSessionSigs` and passed them into `executeJs` / `pkpSign`. + +### v8 + +Create a PKP auth context and pass it to core APIs: + +```ts +import { ViemAccountAuthenticator } from "@lit-protocol/auth"; + +const authData = await ViemAccountAuthenticator.authenticate(myViemAccount); + +const pkpAuthContext = await authManager.createPkpAuthContext({ + authData, + pkpPublicKey: myPkp.pubkey, + authConfig: { + resources: [ + ["pkp-signing", "*"], + ["lit-action-execution", "*"], + ], + expiration: new Date(Date.now() + 30 * 60 * 1000).toISOString(), + }, + litClient, +}); +``` + +## PKP session signatures (wrapped-keys only) + +Wrapped-keys APIs still expect a `pkpSessionSigs` bundle for v7 compatibility. +Generate them in v8 like this: + +```ts +import { generateSessionKeyPair } from "@lit-protocol/auth"; + +const sessionKeyPair = generateSessionKeyPair(); + +const delegationAuthSig = await authManager.generatePkpDelegationAuthSig({ + pkpPublicKey: myPkp.pubkey, + authData, + sessionKeyPair, + authConfig: { + resources: [ + ["pkp-signing", "*"], + ["lit-action-execution", "*"], + ["access-control-condition-decryption", "*"], + ], + expiration: new Date(Date.now() + 15 * 60 * 1000).toISOString(), + }, + litClient, +}); + +const pkpSessionSigs = await authManager.createPkpSessionSigs({ + sessionKeyPair, + pkpPublicKey: myPkp.pubkey, + delegationAuthSig, + litClient, +}); +``` + +# Core API method changes + +## `executeJs` + +### v7 + +```ts +const res = await litNodeClient.executeJs({ + sessionSigs, + code, + jsParams: { magicNumber: 43 }, +}); +``` + +### v8 + +```ts +const res = await litClient.executeJs({ + code, + authContext: eoaAuthContext, + jsParams: { magicNumber: 43 }, +}); +``` + +## Lit Actions runtime: **`jsParams` is now nested** + +This is the biggest Lit Actions breaking change. + +| v7 Lit Action | v8 Lit Action | +| --- | --- | +| `if (magicNumber >= 42) { ... }` | `if (jsParams.magicNumber >= 42) { ... }` | + +In v7, keys in `jsParams` were injected as globals. +In v8, all custom inputs live under the global `jsParams` object. + +Also prefer `Lit.Actions.*` over `LitActions.*` in new actions. + +## `pkpSign` + +### v7 + +```ts +const sig = await litNodeClient.pkpSign({ + pubKey: pkpPubKey, + toSign, + sessionSigs, +}); +``` + +### v8 + +```ts +const sig = await litClient.chain.ethereum.pkpSign({ + pubKey: pkpPubKey, + toSign, + authContext: pkpAuthContext, + // bypassAutoHashing: true, // if you already hashed data (e.g. EIP-712 digest) +}); +``` + +Notes: + +- PKP signing is now grouped by chain (`litClient.chain.ethereum`, `litClient.chain.bitcoin`, or `litClient.chain.raw`). +- Core APIs always require `authContext`; they mint session signatures internally. + +## Encryption / decryption + +### v7 (typical) + +```ts +import { encryptString, decryptToString } from "@lit-protocol/encryption"; + +const encrypted = await encryptString( + { + accessControlConditions, + dataToEncrypt: "secret", + chain: "ethereum", + }, + litNodeClient +); + +const plaintext = await decryptToString( + { + accessControlConditions, + ciphertext: encrypted.ciphertext, + dataToEncryptHash: encrypted.dataToEncryptHash, + chain: "ethereum", + sessionSigs, + }, + litNodeClient +); +``` + +### v8 + +```ts +const encrypted = await litClient.encrypt({ + dataToEncrypt: "secret", + unifiedAccessControlConditions, + chain: "ethereum", +}); + +const plaintext = await litClient.decrypt({ + data: encrypted, + unifiedAccessControlConditions, + authContext: eoaAuthContext, + chain: "ethereum", +}); +``` + +v8 still accepts `accessControlConditions`, `evmContractConditions`, or `solRpcConditions`, but the unified builder (`createAccBuilder`) plus `unifiedAccessControlConditions` is the recommended path. + +# Wrapped Keys migration + +Only two changes for most users: + +1. Pass `litClient` instead of `litNodeClient`. +2. Generate `pkpSessionSigs` via `AuthManager` (section above). + +```ts +import { api as wrappedKeysApi } from "@lit-protocol/wrapped-keys"; + +const { id } = await wrappedKeysApi.generatePrivateKey({ + pkpSessionSigs, + litClient, + network: "evm", +}); +``` + +# Payments: Capacity Credits → Ledger + PaymentManager + +v7 Capacity Credits NFTs and `createCapacityDelegationAuthSig` flows are deprecated in v8. + +In v8: + +- Paid networks (`naga-test`, `naga`) charge per request. +- Users (or your app) fund a Ledger balance. +- Apps can sponsor users by delegating payments. + +## Minimal self‑funded setup + +```ts +const paymentManager = await litClient.getPaymentManager({ + account: myViemAccount, +}); + +await paymentManager.deposit({ amountInEth: "0.1" }); +``` + +Then call core APIs as usual. +Use `userMaxPrice` to cap spend per request: + +```ts +await litClient.executeJs({ + code, + authContext, + jsParams, + userMaxPrice: 1_000_000_000_000_000n, +}); +``` + +## Sponsoring users (replaces Capacity Delegation) + +```ts +await paymentManager.setRestriction({ + totalMaxPrice: "1000000000000000000", // wei + requestsPerPeriod: "100", + periodSeconds: "3600", +}); + +await paymentManager.delegatePaymentsBatch({ + userAddresses: ["0xAlice...", "0xBob..."], +}); +``` + +See [Payment Manager Setup](/sdk/getting-started/payment-manager-setup) for full details. + +# If you used `pkp-ethers` + +The ethers PKP wallets were removed. Two common replacements: + +1. **Use viem account integration** + +```ts +const pkpAccount = await litClient.getPkpViemAccount({ + pkpPublicKey: myPkp.pubkey, + authContext: pkpAuthContext, + chainConfig: myViemChain, +}); +``` + +2. **Call `pkpSign` directly** via `litClient.chain.*.pkpSign` and assemble transactions yourself. + +# Other notable removals / moves + +- `lit-auth-client` and its auth providers are replaced by `@lit-protocol/auth` + optional `@lit-protocol/auth-services`. +- Node‑only vs browser‑only split packages are consolidated; v8 is isomorphic by default. +- Low‑level helpers from v7 still exist in subpackages where applicable, but most apps can migrate to the higher‑level `litClient`/`authManager` APIs shown here. + +# Troubleshooting after upgrade + +## “`magicNumber` is not defined” inside Lit Actions + +Update Lit Action code to read `jsParams.magicNumber` (see runtime section). + +## “Missing peer dependency `viem`” + +Install `viem` and ensure your bundler doesn’t dedupe it away. + +## “Insufficient ledger balance / payment required” + +Deposit funds with `PaymentManager.deposit` or delegate a payer (paid networks only). + +## Wrapped keys failing with “missing pkpSessionSigs” + +Core APIs no longer need session sigs, but wrapped‑keys still do. Generate them via `authManager.createPkpSessionSigs`. + +# Next steps + +- Browse the v8 SDK docs starting at [Lit Client Setup](/sdk/getting-started/lit-client). +- For serverless reuse patterns, see [Server Sessions](/guides/server-sessions). diff --git a/packages/networks/src/networks/vNaga/shared/factories/BaseModuleFactory.ts b/packages/networks/src/networks/vNaga/shared/factories/BaseModuleFactory.ts index a7fc55500..d9813b4cf 100644 --- a/packages/networks/src/networks/vNaga/shared/factories/BaseModuleFactory.ts +++ b/packages/networks/src/networks/vNaga/shared/factories/BaseModuleFactory.ts @@ -907,6 +907,10 @@ export function createBaseModule(config: BaseModuleConfig) { accessToken: requestBody.authData.accessToken, } as AuthMethod; + const maxPriceHex = `0x${getUserMaxPrice({ + product: 'SIGN_SESSION_KEY', + }).toString(16)}`; + const requests: RequestItem< z.infer >[] = []; @@ -921,9 +925,7 @@ export function createBaseModule(config: BaseModuleConfig) { curveType: 'BLS' as const, epoch: requestBody.epoch, nodeSet: requestBody.nodeSet, - maxPrice: getUserMaxPrice({ - product: 'SIGN_SESSION_KEY', - }).toString(), + maxPrice: maxPriceHex, }; const encryptedPayload = E2EERequestManager.encryptRequestData( @@ -1031,6 +1033,28 @@ export function createBaseModule(config: BaseModuleConfig) { (node) => `${httpProtocol}${node.socketAddress}` ); + const encodedCode = requestBody.litActionCode + ? Buffer.from(requestBody.litActionCode, 'utf-8').toString('base64') + : undefined; + + const maxPriceHex = `0x${getUserMaxPrice({ + product: 'SIGN_SESSION_KEY', + }).toString(16)}`; + + // `requestBody.jsParams` can arrive in either shape: + // - raw: `` + // - nested (AuthManager): `{ jsParams: }` via + // `params.customAuthParams.jsParams = { jsParams: params.customAuthParams.jsParams };` + // in `packages/auth/src/lib/AuthManager/auth-manager.ts` + // + // Example: + // - user passes: `{ foo: 1 }` + // - AuthManager wraps: `{ jsParams: { foo: 1 } }` + // - normalized here: `rawJsParams = { foo: 1 }` + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const rawJsParams = + (requestBody.jsParams as any)?.jsParams ?? requestBody.jsParams; + const requests: RequestItem< z.infer >[] = []; @@ -1045,12 +1069,20 @@ export function createBaseModule(config: BaseModuleConfig) { curveType: 'BLS' as const, epoch: requestBody.epoch, nodeSet: requestBody.nodeSet, - litActionCode: requestBody.litActionCode, - litActionIpfsId: requestBody.litActionIpfsId, - jsParams: requestBody.jsParams, - maxPrice: getUserMaxPrice({ - product: 'SIGN_SESSION_KEY', - }).toString(), + ...(encodedCode && { code: encodedCode }), + ...(requestBody.litActionIpfsId && { + litActionIpfsId: requestBody.litActionIpfsId, + }), + ...(rawJsParams && { + // Expose both raw + nested `jsParams` for compatibility: + // - Lit Action can read `jsParams.foo` + // - or `jsParams.jsParams.foo` + jsParams: { + ...rawJsParams, + jsParams: rawJsParams, + }, + }), + maxPrice: maxPriceHex, }; const encryptedPayload = E2EERequestManager.encryptRequestData( diff --git a/packages/wrapped-keys-lit-actions/src/lib/internal/solana/signMessage.ts b/packages/wrapped-keys-lit-actions/src/lib/internal/solana/signMessage.ts index ffc9cdc8c..8680abcd9 100644 --- a/packages/wrapped-keys-lit-actions/src/lib/internal/solana/signMessage.ts +++ b/packages/wrapped-keys-lit-actions/src/lib/internal/solana/signMessage.ts @@ -39,10 +39,11 @@ function verifyMessageSignature({ messageToSign, }: VerifyMessageSignatureParams): boolean { try { + const messageBytes = new TextEncoder().encode(messageToSign); const isValid = nacl.sign.detached.verify( - Buffer.from(messageToSign), + messageBytes, signature, - solanaKeyPair.publicKey.toBuffer() + solanaKeyPair.publicKey.toBytes() ); return isValid; @@ -62,7 +63,8 @@ export async function signMessageSolanaKey({ messageToSign: string; privateKey: string; }): Promise { - const solanaKeyPair = Keypair.fromSecretKey(Buffer.from(privateKey, 'hex')); + const privateKeyBytes = Uint8Array.from(Buffer.from(privateKey, 'hex')); + const solanaKeyPair = Keypair.fromSecretKey(privateKeyBytes); const { signature } = signMessage({ messageToSign, diff --git a/packages/wrapped-keys-lit-actions/src/lib/internal/solana/signTransaction.ts b/packages/wrapped-keys-lit-actions/src/lib/internal/solana/signTransaction.ts index a9aba72e7..3bf69e842 100644 --- a/packages/wrapped-keys-lit-actions/src/lib/internal/solana/signTransaction.ts +++ b/packages/wrapped-keys-lit-actions/src/lib/internal/solana/signTransaction.ts @@ -98,21 +98,22 @@ export async function signTransactionSolanaKey({ }) { // Be sure you call validateUnsignedTransaction(unsignedTransaction); before calling this method! - const solanaKeyPair = Keypair.fromSecretKey(Buffer.from(privateKey, 'hex')); + const privateKeyBytes = Uint8Array.from(Buffer.from(privateKey, 'hex')); + const solanaKeyPair = Keypair.fromSecretKey(privateKeyBytes); let transaction; let signature; if (versionedTransaction) { - const swapTransactionBuf = Buffer.from( - unsignedTransaction.serializedTransaction, - 'base64' + const serializedTxBytes = Uint8Array.from( + Buffer.from(unsignedTransaction.serializedTransaction, 'base64') ); - transaction = VersionedTransaction.deserialize(swapTransactionBuf); + transaction = VersionedTransaction.deserialize(serializedTxBytes); signature = signVersionedTransaction({ transaction, solanaKeyPair }); } else { - transaction = Transaction.from( + const serializedTxBytes = Uint8Array.from( Buffer.from(unsignedTransaction.serializedTransaction, 'base64') ); + transaction = Transaction.from(serializedTxBytes); signature = signLegacyTransaction({ transaction, solanaKeyPair }); }