Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
79 commits
Select commit Hold shift + click to select a range
be3d59a
chore(PR): init
Ansonhkg Aug 13, 2025
205f686
chore(PR): init
Ansonhkg Aug 13, 2025
99e5f5c
chore(PR): init branch
Ansonhkg Aug 13, 2025
0c88db1
feat(wip): add pre-generated materials support
Ansonhkg Aug 14, 2025
70c5bc7
Merge branch 'naga' into feature/jss-36-naga-sdk-add-a-make-a-request…
Ansonhkg Aug 25, 2025
14d6124
Merge branch 'naga' into feature/jss-36-naga-sdk-add-a-make-a-request…
Ansonhkg Aug 25, 2025
1e91e94
Merge branch 'feature/jss-36-naga-sdk-add-a-make-a-request-function-t…
Ansonhkg Aug 25, 2025
dfaca3f
Merge branch 'naga' into feature/jss-36-naga-sdk-add-a-make-a-request…
Ansonhkg Oct 14, 2025
1d2dbe0
refactor(getPkpAuthContext): improve logging format for delegationAut…
Ansonhkg Oct 14, 2025
82d33f1
feat(validateDelegationAuthSig): add function to validate delegation …
Ansonhkg Oct 14, 2025
6c9f0f6
feat(auth): enhance delegation signature handling and validation in a…
Ansonhkg Oct 14, 2025
27c9645
Merge branch 'naga' into feature/jss-36-naga-sdk-add-a-make-a-request…
Ansonhkg Oct 15, 2025
c74ae30
feat(validateDelegationAuthSig): add unit tests for delegation signat…
Ansonhkg Oct 15, 2025
720830d
feat(auth): export `validateDelegationAuthSig` helper
Ansonhkg Oct 15, 2025
be3eb44
fix(auth): validateDelegationAuthSig params
Ansonhkg Oct 15, 2025
de1fa5a
Merge branch 'feature/jss-36-naga-sdk-add-a-make-a-request-function-t…
Ansonhkg Oct 15, 2025
c5bc50e
feat(auth): derive recap metadata for pre-generated PKP contexts
Ansonhkg Oct 16, 2025
f6152f6
feat(auth): add test
Ansonhkg Oct 16, 2025
dd2bac9
fmt
Ansonhkg Oct 16, 2025
eb2138f
feat(ci): add test to ci
Ansonhkg Oct 16, 2025
a9381e8
Merge branch 'naga' into feature/jss-36-naga-sdk-add-a-make-a-request…
Ansonhkg Oct 16, 2025
83cf3cf
feat(e2e): centralise pre-generated delegation reuse helper
Ansonhkg Oct 16, 2025
29d011a
Merge branch 'feature/jss-36-naga-sdk-add-a-make-a-request-function-t…
Ansonhkg Oct 16, 2025
68ffaa9
refactor(tests): update createPregenDelegationServerReuseTest to acce…
Ansonhkg Oct 16, 2025
b6c9d9d
refactor(network): replace networkName with resolvedNetwork in variou…
Ansonhkg Oct 16, 2025
1930dea
fmt
Ansonhkg Oct 16, 2025
4c0da86
fix(tests): simplify test syntax
Ansonhkg Oct 16, 2025
332cd51
refactor(constants, wrapped-keys): remove `GLOBAL_OVERWRITE_IPFS_CODE…
Ansonhkg Oct 17, 2025
6d5d004
refactor(network): add NagaTest network support and update related co…
Ansonhkg Oct 17, 2025
9f8b91f
refactor(config): clear ignore list in changeset configuration
Ansonhkg Oct 17, 2025
7913862
refactor(mappers): remove unused network context mapping
Ansonhkg Oct 17, 2025
b3e4576
feat(networks): exports `PricingContextSchema` and `issueSessionFromC…
Ansonhkg Oct 17, 2025
46b4de3
chore(e2e): making sure pregen works
Ansonhkg Oct 20, 2025
f044ae9
feat(wrapped-keys, wrapped-keys-lit-actions): add wrapped keys featur…
Ansonhkg Oct 23, 2025
243d4a1
feat(auth): add `createPkpSessionSigs
Ansonhkg Oct 23, 2025
3df541d
feat(lit-client): fix and add `NagaLitClient` with improved type defi…
Ansonhkg Oct 23, 2025
9f49188
feat(networks): add `sessionSigs` support
Ansonhkg Oct 23, 2025
23bec70
feat(e2e): add wrapped-keys test
Ansonhkg Oct 23, 2025
dbbe54f
feat(wrapped-keys): add tests for `solana` wrapped keys
Ansonhkg Oct 23, 2025
8142b5e
feat(test): restruct for wrapped keys
Ansonhkg Oct 23, 2025
1ae7240
fix: resolve comments
Ansonhkg Oct 23, 2025
de71681
Merge branch 'naga' of github.com:LIT-Protocol/js-sdk into feature/js…
Ansonhkg Oct 23, 2025
82423ef
fix(wrapped-keys-la): add `form-data` for the sync script
Ansonhkg Oct 23, 2025
4609e65
fmt
Ansonhkg Oct 23, 2025
1cd03ad
fix: remove packageManager
Ansonhkg Oct 23, 2025
123ab63
fix(wrapped-keys-lit-actions): sync script
Ansonhkg Oct 23, 2025
51e4e3e
feat(wrapped-keys): add `userMaxPrice` to the params
Ansonhkg Oct 23, 2025
d770f8b
refactor: remove unused session signature helpers
Ansonhkg Oct 23, 2025
2ee91bf
feat(wrapped-keys-la): update lit action CIDs and improve constants f…
Ansonhkg Oct 23, 2025
023e305
fix: update sync script and clean up constants file
Ansonhkg Oct 23, 2025
d7618b8
feat(docs): add `wrapped-keys` reference
Ansonhkg Oct 23, 2025
21bff7e
fix: rebuild lit actions before running e2e suites
Ansonhkg Oct 23, 2025
9b4fe96
feat(test): add more tests for Solana
Ansonhkg Oct 23, 2025
d49e460
feat(docs): add `wrapped-keys` docs
Ansonhkg Oct 23, 2025
ff49ddd
fix(docs): fix broken link
Ansonhkg Oct 23, 2025
89dcc3a
fix(docs): update link text for wrapped keys reference
Ansonhkg Oct 23, 2025
48c20c0
fix(docs): fix broken link
Ansonhkg Oct 23, 2025
ff1b8bb
fix(wk-la): extra `;` in the gen code
Ansonhkg Oct 23, 2025
0a80342
chore: add changeset
Ansonhkg Oct 23, 2025
59c2bef
feat(docs): add delegation auth signature functions and examples
Ansonhkg Oct 23, 2025
5b686da
feat(docs): add wrapped-keys support and new APIs for key management …
Ansonhkg Oct 23, 2025
7675fa3
fix(schema): change sessionSigs type from never to undefined in auth …
Ansonhkg Oct 23, 2025
1fc4b6b
Merge branch 'naga' into feature/jss-35-naga-js-sdk-wrapped-keys-impl…
Ansonhkg Oct 24, 2025
3b3967a
fix(lit-client): fix `utils` type
Ansonhkg Oct 24, 2025
38b9b36
feat(e2e): add wrapped keys health check
Ansonhkg Oct 24, 2025
a2fda68
Merge branch 'naga' into feature/jss-35-naga-js-sdk-wrapped-keys-impl…
Ansonhkg Oct 27, 2025
5374f72
fix(docs): typo
Ansonhkg Oct 27, 2025
082ddf1
docs: add a section to explain Lit resources
Ansonhkg Oct 28, 2025
ebc21dc
Merge branch 'naga' of github.com:LIT-Protocol/js-sdk into feature/js…
Ansonhkg Oct 29, 2025
5876ab8
Merge branch 'naga' into feature/jss-35-naga-js-sdk-wrapped-keys-impl…
Ansonhkg Oct 30, 2025
13e8acb
Merge branch 'naga' into feature/jss-35-naga-js-sdk-wrapped-keys-impl…
Ansonhkg Oct 30, 2025
e36e0a4
Merge branch 'naga' of github.com:LIT-Protocol/js-sdk into feature/js…
Ansonhkg Oct 30, 2025
01caffa
fix(e2e): add exports for test files
Ansonhkg Oct 30, 2025
1d47b5d
Merge branch 'naga' into feature/jss-35-naga-js-sdk-wrapped-keys-impl…
Ansonhkg Oct 31, 2025
5aef434
Merge branch 'naga' into feature/jss-35-naga-js-sdk-wrapped-keys-impl…
Ansonhkg Oct 31, 2025
9dbbdbb
fmt
Ansonhkg Oct 31, 2025
cc17ec2
fix: update funding condition in wrappedKeys tests
Ansonhkg Oct 31, 2025
d6808dc
Merge branch 'naga' into feature/jss-35-naga-js-sdk-wrapped-keys-impl…
Ansonhkg Oct 31, 2025
9610e39
Merge branch 'naga' into feature/jss-35-naga-js-sdk-wrapped-keys-impl…
Ansonhkg Nov 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .changeset/cold-dancers-push.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
'@lit-protocol/wrapped-keys-lit-actions': minor
'@lit-protocol/auth-services': minor
'@lit-protocol/auth-helpers': minor
'@lit-protocol/wrapped-keys': minor
'@lit-protocol/lit-client': minor
'@lit-protocol/artillery': minor
'@lit-protocol/constants': minor
'@lit-protocol/contracts': minor
'@lit-protocol/networks': minor
'@lit-protocol/crypto': minor
'@lit-protocol/auth': minor
'@lit-protocol/e2e': minor
---

Introduce wrapped-keys support to v8 so applications can generate, import, export, and sign with encrypted keys across EVM and Solana without exposing private key material. New `auth` package APIs include `validateDelegationAuthSig`, `generatePkpDelegationAuthSig`, `generateEoaDelegationAuthSig`, `createPkpAuthContextFromPreGenerated`, and `createPkpSessionSigs`. New `wrapped-keys` APIs include `generatePrivateKey`, `importPrivateKey`, `exportPrivateKey`, `listEncryptedKeyMetadata`, `getEncryptedKey`, `storeEncryptedKey`, `storeEncryptedKeyBatch`, `batchGeneratePrivateKeys`, `signMessageWithEncryptedKey`, and `signTransactionWithEncryptedKey`. See the updated docs (guides/server-sessions, sdk-reference/wrapped-keys, and the new auth references) for end-to-end examples. [PR](https://github.com/LIT-Protocol/js-sdk/pull/972)
5 changes: 1 addition & 4 deletions .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,5 @@
"access": "public",
"baseBranch": "naga",
"updateInternalDependencies": "minor",
"ignore": [
"@lit-protocol/wrapped-keys",
"@lit-protocol/wrapped-keys-lit-actions"
]
"ignore": []
}
31 changes: 27 additions & 4 deletions docs/docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,8 @@
"pages": [
"sdk/auth-context-consumption/pkp-sign",
"sdk/auth-context-consumption/execute-js",
"sdk/auth-context-consumption/encrypt-and-decrypt"
"sdk/auth-context-consumption/encrypt-and-decrypt",
"sdk/auth-context-consumption/wrapped-keys"
]
},
{
Expand Down Expand Up @@ -109,14 +110,35 @@
{
"group": "@lit-protocol/auth",
"pages": [
"sdk/sdk-reference/auth/functions/createAuthManager"
"sdk/sdk-reference/auth/functions/createAuthManager",
"sdk/sdk-reference/auth/functions/generatePkpDelegationAuthSig",
"sdk/sdk-reference/auth/functions/generateEoaDelegationAuthSig",
"sdk/sdk-reference/auth/functions/validateDelegationAuthSig",
"sdk/sdk-reference/auth/functions/createPkpAuthContextFromPreGenerated",
"sdk/sdk-reference/auth/functions/createPkpSessionSigs"
]
},
{
"group": "@lit-protocol/networks",
"pages": [
"sdk/sdk-reference/networks/functions/withOverrides"
]
},
{
"group": "@lit-protocol/wrapped-keys",
"pages": [
"sdk/sdk-reference/wrapped-keys/index",
"sdk/sdk-reference/wrapped-keys/functions/generatePrivateKey",
"sdk/sdk-reference/wrapped-keys/functions/exportPrivateKey",
"sdk/sdk-reference/wrapped-keys/functions/importPrivateKey",
"sdk/sdk-reference/wrapped-keys/functions/getEncryptedKey",
"sdk/sdk-reference/wrapped-keys/functions/listEncryptedKeyMetadata",
"sdk/sdk-reference/wrapped-keys/functions/storeEncryptedKey",
"sdk/sdk-reference/wrapped-keys/functions/storeEncryptedKeyBatch",
"sdk/sdk-reference/wrapped-keys/functions/batchGeneratePrivateKeys",
"sdk/sdk-reference/wrapped-keys/functions/signMessageWithEncryptedKey",
"sdk/sdk-reference/wrapped-keys/functions/signTransactionWithEncryptedKey"
]
}
]
},
Expand All @@ -130,7 +152,8 @@
{
"group": "Guides",
"pages": [
"guides/lit-action-sign-as-action"
"guides/lit-action-sign-as-action",
"guides/server-sessions"
]
},
{
Expand Down Expand Up @@ -221,4 +244,4 @@
"discord": "https://litgateway.com/discord"
}
}
}
}
126 changes: 126 additions & 0 deletions docs/guides/server-sessions.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
---
title: "Server Sessions"
description: "Delegate a PKP to an ephemeral session key and hand that scoped capability to backend services that mint fresh session signatures on demand."
---

# Overview

Some integrations need a backend or serverless worker to execute Lit actions long after a user has left the client. Instead of caching `pkpSessionSigs` (which expire quickly and can become invalid when nodes join or leave the network), you can delegate the PKP to a session key and send the **session keypair plus delegation auth signature** to the server. The server then recreates the auth context and generates short-lived session signatures immediately before each request.

This pattern keeps the delegation scoped (resources and expiration are enforced by the delegation) while avoiding the flakiness that comes from reusing stale session signatures.

# Workflow

1. **Client generates a session keypair** with `generateSessionKeyPair()`.
2. **Client creates a delegation auth signature** with `authManager.generatePkpDelegationAuthSig`, scoping the allowed [Lit resources](/sdk/resources/lit-resources-and-abilities) and expiration.
3. **Client sends the bundle** { sessionKeyPair, delegationAuthSig, pkpPublicKey }` to the server over a secure channel.
4. **Server restores an auth context** using `authManager.createPkpAuthContextFromPreGenerated`.
5. **Server issues fresh session signatures on demand** (e.g., `authManager.createPkpSessionSigs`) immediately before calling SDK helpers such as the wrapped-keys API or `pkpSign`.

# Client hand-off example

```ts
import {
createAuthManager,
generateSessionKeyPair,
} from '@lit-protocol/auth';

const sessionKeyPair = generateSessionKeyPair();

const delegationAuthSig = await authManager.generatePkpDelegationAuthSig({
pkpPublicKey,
authData,
sessionKeyPair,
authConfig: {
resources: [
['pkp-signing', '*'],
['lit-action-execution', '*'],
['access-control-condition-decryption', '*'],
],
expiration: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
},
litClient: litClient,
});

const envelope = JSON.stringify({
pkpPublicKey,
payload: Buffer.from(
JSON.stringify({ sessionKeyPair, delegationAuthSig }),
'utf8'
).toString('base64url'),
});
```

# Server restore example

```ts
import {
createAuthManager,
storagePlugins,
validateDelegationAuthSig,
} from '@lit-protocol/auth';
import { createLitClient } from '@lit-protocol/lit-client';

const parsedEnvelope = JSON.parse(envelope) as {
pkpPublicKey: string;
payload: string;
};

const decodedPayload = JSON.parse(
Buffer.from(parsedEnvelope.payload, 'base64url').toString('utf8')
) as {
sessionKeyPair: typeof sessionKeyPair;
delegationAuthSig: typeof delegationAuthSig;
};

validateDelegationAuthSig({
delegationAuthSig: decodedPayload.delegationAuthSig,
sessionKeyUri: decodedPayload.sessionKeyPair.publicKey,
});

const serverLitClient = await createLitClient({ network: resolvedNetwork });
const serverAuthManager = createAuthManager({
storage: storagePlugins.localStorageNode({
appName: 'server-session-demo',
networkName: resolvedNetwork.name,
storagePath: './.server-session-cache',
}),
});

const authContext =
await serverAuthManager.createPkpAuthContextFromPreGenerated({
pkpPublicKey: parsedEnvelope.pkpPublicKey,
sessionKeyPair: decodedPayload.sessionKeyPair,
delegationAuthSig: decodedPayload.delegationAuthSig,
});

// Only call this when the downstream API explicitly requires session sigs
const pkpSessionSigs = await serverAuthManager.createPkpSessionSigs({
sessionKeyPair: decodedPayload.sessionKeyPair,
pkpPublicKey: parsedEnvelope.pkpPublicKey,
delegationAuthSig: decodedPayload.delegationAuthSig,
litClient: serverLitClient,
});

await serverLitClient.chain.ethereum.pkpSign({
authContext,
pubKey: parsedEnvelope.pkpPublicKey,
toSign: 'hello from server reuse',
});
```

<Note>
Only call `createPkpSessionSigs` when the downstream API explicitly requires the session sigs (for example, the wrapped-keys service).
</Note>

# Security considerations

- **Treat the session keypair like a secret.** Whoever holds the private key can mint new session signatures until the delegation expires.
- **Scope the delegation.** Restrict resources to the minimal [Lit resources](/sdk/resources/lit-resources-and-abilities) needed and set conservative expirations.
- **Rotate on failure.** If a node joins or leaves the network the server can simply regenerate session signatures with the current handshake; if that fails, request a fresh delegation from the client.

# When to use this pattern

- Long-running workflows where session signatures might expire before all steps finish (e.g., Bitcoin transactions that need multiple confirmations).
- Server-driven orchestration that must run without a browser tab staying open.
- Integrations that want to avoid caching `pkpSessionSigs`, but still need durable delegated access.
146 changes: 146 additions & 0 deletions docs/sdk/auth-context-consumption/wrapped-keys.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
---
title: "Wrapped Keys"
description: "Manage generated or imported keys through Lit’s wrapped-keys service by delegating a PKP session and calling the specialised APIs for EVM and Solana."
---

# Overview

Wrapped keys let you generate, import, store, and use non-PKP private keys while keeping them encrypted by the Lit Network. The `@lit-protocol/wrapped-keys` package exposes helper APIs that run curated Lit Actions via `executeJs` for you so that signed messages or transactions never leave the Lit node unless you explicitly export the key material.

Unlike the Core API flows (`pkpSign`, `executeJs`, `encryptAndDecrypt`) that accept an `authContext` directly, the wrapped-keys APIs expect a PKP session signature bundle (`pkpSessionSigs`). This keeps the SDK compatible with the v7 infrastructure and Lambda/serverless deployments that pass session materials between runtimes. Mint the bundle with `authManager.createPkpSessionSigs` as shown below.

# How the flow differs from other Core API methods

- **Why generate a delegation auth sig?**
You delegate your PKP to an ephemeral session key so the wrapped-keys Lit Actions can execute without presenting your long-lived auth credentials. The delegation constrains the permissions (`pkp-signing`, `lit-action-execution`, `access-control-condition-decryption`) and sets an expiry window, limiting blast radius if the session key is ever leaked. Refer to the [Lit resources guide](/sdk/resources/lit-resources-and-abilities) for the full catalogue of resource prefixes and abilities.

- **Why supply PKP session signatures?**
Wrapped-keys endpoints reuse the same session bundle across all networks (for example, Lambda functions in the v7 stack). Provide `pkpSessionSigs` produced by `authManager.createPkpSessionSigs` so the Lit nodes can verify the delegated permissions before executing the action.

- **Controlling network spend**
Because every wrapped-keys helper ultimately calls `executeJs`, you can supply an optional `userMaxPrice` to cap how much a caller is willing to pay for node execution (mirroring the parameter available on the core `executeJs` API).

- **Optional: bundle Lit Action source**
By default the SDK references IPFS CIDs. To remove the IPFS dependency, inject the Lit Action source code at runtime:

```ts
import { api as wrappedKeysApi, config as wrappedKeysConfig } from '@lit-protocol/wrapped-keys';
import {
litActionRepository,
litActionRepositoryCommon,
} from '@lit-protocol/wrapped-keys-lit-actions';

wrappedKeysConfig.setLitActionsCode(litActionRepository);
wrappedKeysConfig.setLitActionsCodeCommon(litActionRepositoryCommon);
```

# Session material workflow

```ts
import { createAuthManager, generateSessionKeyPair } from '@lit-protocol/auth';
import { api as wrappedKeysApi } from '@lit-protocol/wrapped-keys';

const authManager = createAuthManager();
const litClient = await createLitClient({ network: resolvedNetwork });

// 1. Ephemeral signer that will front the PKP for wrapped-key actions
const sessionKeyPair = generateSessionKeyPair();

// 2. Delegate the PKP to the session key with explicit Lit resources and expiry
const delegationAuthSig = await authManager.generatePkpDelegationAuthSig({
pkpPublicKey,
authData,
sessionKeyPair,
authConfig: {
resources: [
['pkp-signing', '*'],
['lit-action-execution', '*'],
['access-control-condition-decryption', '*'],
],
expiration: new Date(Date.now() + 15 * 60 * 1000).toISOString(),
},
litClient,
});

// 3. Produce the SessionSigsMap required by every wrapped-keys API call
const pkpSessionSigs = await authManager.createPkpSessionSigs({
sessionKeyPair,
pkpPublicKey,
delegationAuthSig,
litClient,
});

// 4. Call wrapped-keys APIs with the session signatures
const { id } = await wrappedKeysApi.generatePrivateKey({
pkpSessionSigs,
litClient,
network: 'evm',
memo: 'wallet for gasless relays',
userMaxPrice: 1000n, // optional cap on per-request spend
});
```

<Note>
Wrapped-keys calls need `pkpSessionSigs` explicitly. Other Lit APIs that accept an `authContext` (for example `executeJs` or `pkpSign`) creates session signatures internally, so you do not need to export it when you are not touching wrapped keys.
</Note>

Need a backend to create fresh session signatures on demand? Follow the [server sessions guide](/guides/server-sessions) to delegate a session key and let the server recreate `pkpSessionSigs` per request.

# Example usage

## Generate and sign on EVM

```ts
const { id, generatedPublicKey } = await wrappedKeysApi.generatePrivateKey({
pkpSessionSigs,
litClient,
network: 'evm',
memo: 'lit',
});

// Export once if you need the raw private key
const { decryptedPrivateKey } = await wrappedKeysApi.exportPrivateKey({
pkpSessionSigs,
litClient,
network: 'evm',
id,
});

// Sign an EVM transaction without revealing the key outside the Lit nodes
const serializedTx = await wrappedKeysApi.signTransactionWithEncryptedKey({
pkpSessionSigs,
litClient,
network: 'evm',
id,
unsignedTransaction: {
chain: 'yellowstone',
chainId: 175188,
toAddress: '0x0000000000000000000000000000000000000000',
value: '0',
},
broadcast: false,
});
```

## Generate and sign on Solana

```ts
const { id, publicKey } = await wrappedKeysApi.generatePrivateKey({
pkpSessionSigs,
litClient,
network: 'solana',
memo: 'vault signer',
});

const signature = await wrappedKeysApi.signMessageWithEncryptedKey({
pkpSessionSigs,
litClient,
network: 'solana',
id,
messageToSign: 'hello from wrapped keys',
});
```

# API catalogue

See the full reference for every helper at [Wrapped Keys Reference](/sdk/sdk-reference/wrapped-keys/index).
Loading
Loading