Skip to content

docs: Add security token locking docs for TS SDK and TS Compat SDK v1.2.0#123

Open
ihsraham wants to merge 2 commits intomasterfrom
feat/sdk-v1.2.0-docs
Open

docs: Add security token locking docs for TS SDK and TS Compat SDK v1.2.0#123
ihsraham wants to merge 2 commits intomasterfrom
feat/sdk-v1.2.0-docs

Conversation

@ihsraham
Copy link
Collaborator

@ihsraham ihsraham commented Mar 8, 2026

Summary

Adds documentation for the v1.2.0 security token locking features across both the TypeScript SDK and TypeScript Compat SDK docs.

TypeScript SDK Docs

  • api-reference.mdx: New "Security Token Locking" section documenting all 6 methods: approveSecurityToken, escrowSecurityTokens, getLockedBalance, initiateSecurityTokensWithdrawal, cancelSecurityTokensWithdrawal, withdrawSecurityTokens
  • examples.mdx: New "Security Token Locking" example showing approve → lock → balance check → register app flow
  • configuration.mdx: New "Blockchain Configuration" section documenting lockingContractAddress in the Blockchain type

TypeScript Compat SDK Docs

  • overview.mdx: Updated method cheat sheets with all new v1.2.0 compat methods:
    • Security Token Locking (6 methods)
    • App Registry (getApps, registerApp)
    • Additional queries (getBlockchains, getActionAllowances, getEscrowChannel, checkTokenAllowance)
    • Channel operations (acknowledge)
    • App sessions (rebalanceAppSessions)
    • Lifecycle (waitForClose)
    • OngoingStateTransitionError in error table
    • New locking usage example section
    • Fix getUserFacingMessage(err)getUserFacingMessage(typed) in error example

Test Plan

  • Verify docs build with npm run build
  • Review rendered pages for formatting

Summary by CodeRabbit

  • Documentation
    • Added Security Token Locking docs and usage examples for approving, escrowing, checking locked balances, and withdrawing tokens.
    • Introduced new public methods for channel operations, queries, app registry, app sessions, and lifecycle (e.g., waitForClose).
    • Clarified blockchain configuration and home blockchain setup for locking support.
    • Added a typed OngoingStateTransitionError and updated user-facing error messaging.

….2.0

TS SDK (api-reference.mdx):
- Add Security Token Locking section with all 6 methods:
  approveSecurityToken, escrowSecurityTokens, getLockedBalance,
  initiateSecurityTokensWithdrawal, cancelSecurityTokensWithdrawal,
  withdrawSecurityTokens

TS SDK (examples.mdx):
- Add locking + app registration example

TS SDK (configuration.mdx):
- Document lockingContractAddress in blockchain config

TS Compat SDK (overview.mdx):
- Add Security Token Locking method cheat sheet
- Add locking usage example section
- Add acknowledge, checkTokenAllowance, getBlockchains,
  getActionAllowances, getEscrowChannel to queries table
- Add App Registry table (getApps, registerApp)
- Add rebalanceAppSessions, waitForClose
- Add OngoingStateTransitionError to error table
- Fix getUserFacingMessage(err) -> getUserFacingMessage(typed)

Made-with: Cursor
@ihsraham ihsraham requested a review from dpatsora as a code owner March 8, 2026 07:10
@coderabbitai
Copy link

coderabbitai bot commented Mar 8, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 014f263e-db96-4b9f-9353-3a78ade5ad4a

📥 Commits

Reviewing files that changed from the base of the PR and between 428f01f and 36e7f9e.

📒 Files selected for processing (1)
  • docs/build/sdk/typescript-compat/overview.mdx

📝 Walkthrough

Walkthrough

Updates TypeScript SDK docs: adds Security Token Locking feature and methods, expands queries and registry APIs, adds lifecycle/wait helper and new OngoingStateTransitionError, updates configuration and examples (duplicated locking example present).

Changes

Cohort / File(s) Summary
Security Token Locking
docs/build/sdk/typescript-compat/overview.mdx, docs/build/sdk/typescript/api-reference.mdx, docs/build/sdk/typescript/configuration.mdx, docs/build/sdk/typescript/examples.mdx
Adds a Security Token Locking section and six methods (approveSecurityToken, lock/escrowSecurityTokens, getLockedBalance, initiateSecurityTokensWithdrawal, cancelSecurityTokensWithdrawal, withdrawSecurityTokens); documents lockingContractAddress in chain config and includes usage examples (examples.mdx contains a duplicated example).
API Expansions & Error Handling
docs/build/sdk/typescript-compat/overview.mdx
Introduces Channel Operations methods (acknowledge, checkTokenAllowance), Queries (getBlockchains, getActionAllowances, getEscrowChannel), App Sessions (rebalanceAppSessions), App Registry (getApps, registerApp), Lifecycle (waitForClose), and new error type OngoingStateTransitionError; updates error handling examples to use typed errors.
Configuration & Home Blockchain
docs/build/sdk/typescript/configuration.mdx
Adds Blockchain Configuration docs for getConfig()/getBlockchains() output (chain.name, chain.id, channelHubAddress, optional lockingContractAddress) and clarifies setHomeBlockchain(asset, blockchainId) usage before transfers.

Sequence Diagram(s)

sequenceDiagram
    participant User as User/Wallet
    participant Client as SDK Client
    participant Lock as LockingContract (on-chain)
    participant Chain as Blockchain

    User->>Client: request approveSecurityToken(chainId, amount)
    Client->>Lock: send ERC20 approve tx
    Lock-->>Chain: tx mined / approval recorded
    User->>Client: request escrowSecurityTokens(chainId, amount)
    Client->>Lock: call escrow/lock tokens (escrow tx)
    Lock-->>Chain: tx mined / tokens locked
    Client->>Chain: getLockedBalance(chainId, wallet?)
    Chain-->>Client: return locked balance
    Client->>User: return result / receipts
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Suggested reviewers

  • dpatsora

Poem

🐰
Hop, hop — coins tucked tight,
Locks set under moonlit night.
Docs sprout paths to bind and free,
New calls hum in harmony,
I nibble bugs and sip my tea.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title clearly and concisely summarizes the main change: adding security token locking documentation for both TS SDK and TS Compat SDK v1.2.0.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/sdk-v1.2.0-docs
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

You can validate your CodeRabbit configuration file in your editor.

If your editor has YAML language server, you can enable auto-completion and validation by adding # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json at the top of your CodeRabbit configuration file.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/build/sdk/typescript-compat/overview.mdx (1)

216-223: ⚠️ Potential issue | 🟠 Major

Import NitroliteClient in this error-handling snippet.

Line 222 calls NitroliteClient.classifyError(err), but the import only brings in getUserFacingMessage and AllowanceError. As written, the example does not compile when copied.

🩹 Proposed fix
-import { getUserFacingMessage, AllowanceError } from '@yellow-org/sdk-compat';
+import {
+  NitroliteClient,
+  getUserFacingMessage,
+  AllowanceError,
+} from '@yellow-org/sdk-compat';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/build/sdk/typescript-compat/overview.mdx` around lines 216 - 223, The
snippet calls NitroliteClient.classifyError(err) but NitroliteClient is not
imported; update the import statement to include NitroliteClient alongside
getUserFacingMessage and AllowanceError so the example compiles. Locate the
import line that currently reads import { getUserFacingMessage, AllowanceError }
from '@yellow-org/sdk-compat'; and add NitroliteClient to that named import
list.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/build/sdk/typescript/api-reference.mdx`:
- Around line 151-153: Update the "Security Token Locking" intro to include a
short "Requires:" note: state that these on-chain NonSlashableAppRegistry
methods (used for staking security tokens and gated allowances) are available
only when the SDK is configured with lockingContractAddress and must be invoked
via withBlockchainRPC(); mention both the config key lockingContractAddress and
the withBlockchainRPC() helper so readers don't assume the methods work on any
chain.

In `@docs/build/sdk/typescript/configuration.mdx`:
- Around line 60-70: The docs currently conflate the return shapes of
getConfig() and getBlockchains(); update the text and examples to disambiguate
by showing two short examples: one that calls getConfig() and accesses the array
via config.blockchains (e.g., const config = await client.getConfig(); for
(const chain of config.blockchains) { ... }) and a second that calls
getBlockchains() which returns the array directly (e.g., const blockchains =
await client.getBlockchains(); for (const chain of blockchains) { ... }), and/or
add a single clarifying sentence explicitly stating that getBlockchains()
returns the blockchain array while getConfig() returns an envelope object with a
blockchains property.

In `@docs/build/sdk/typescript/examples.mdx`:
- Around line 358-391: The example function lockAndRegisterApp currently calls
client.close() only on the success path; wrap the main flow in a try/finally so
the WebSocket client is always closed: declare the client variable outside the
try, assign it via Client.create(...) inside the try, perform
approveSecurityToken, escrowSecurityTokens, getLockedBalance, and registerApp
inside the try, and call await client.close() in the finally (checking the
client is non-null) to guarantee cleanup even on errors.

---

Outside diff comments:
In `@docs/build/sdk/typescript-compat/overview.mdx`:
- Around line 216-223: The snippet calls NitroliteClient.classifyError(err) but
NitroliteClient is not imported; update the import statement to include
NitroliteClient alongside getUserFacingMessage and AllowanceError so the example
compiles. Locate the import line that currently reads import {
getUserFacingMessage, AllowanceError } from '@yellow-org/sdk-compat'; and add
NitroliteClient to that named import list.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3a61505a-8911-4e84-92f2-51e8e35a6504

📥 Commits

Reviewing files that changed from the base of the PR and between 94e7de5 and 428f01f.

📒 Files selected for processing (4)
  • docs/build/sdk/typescript-compat/overview.mdx
  • docs/build/sdk/typescript/api-reference.mdx
  • docs/build/sdk/typescript/configuration.mdx
  • docs/build/sdk/typescript/examples.mdx

Comment on lines +151 to +153
## Security Token Locking

Methods for interacting with the on-chain Locking (NonSlashableAppRegistry) contract. Used for staking security tokens to register apps and receive gated action allowances.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add the locking prerequisites to the section intro.

This reads as if the six methods are available on any chain. The new configuration docs say locking is only supported when lockingContractAddress is present, and these are still on-chain calls that need withBlockchainRPC(). A short Requires: note here would prevent copy-paste failures.

✏️ Proposed doc tweak
 ## Security Token Locking
 
 Methods for interacting with the on-chain Locking (NonSlashableAppRegistry) contract. Used for staking security tokens to register apps and receive gated action allowances.
+
+**Requires:** `withBlockchainRPC()` for the target chain, and a blockchain whose config includes `lockingContractAddress`.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
## Security Token Locking
Methods for interacting with the on-chain Locking (NonSlashableAppRegistry) contract. Used for staking security tokens to register apps and receive gated action allowances.
## Security Token Locking
Methods for interacting with the on-chain Locking (NonSlashableAppRegistry) contract. Used for staking security tokens to register apps and receive gated action allowances.
**Requires:** `withBlockchainRPC()` for the target chain, and a blockchain whose config includes `lockingContractAddress`.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/build/sdk/typescript/api-reference.mdx` around lines 151 - 153, Update
the "Security Token Locking" intro to include a short "Requires:" note: state
that these on-chain NonSlashableAppRegistry methods (used for staking security
tokens and gated allowances) are available only when the SDK is configured with
lockingContractAddress and must be invoked via withBlockchainRPC(); mention both
the config key lockingContractAddress and the withBlockchainRPC() helper so
readers don't assume the methods work on any chain.

Comment on lines +60 to +70
The node's `getConfig()` and `getBlockchains()` methods return blockchain details including contract addresses:

```typescript
const config = await client.getConfig();
for (const chain of config.blockchains) {
console.log(`${chain.name} (${chain.id})`);
console.log(` ChannelHub: ${chain.channelHubAddress}`);
if (chain.lockingContractAddress) {
console.log(` Locking: ${chain.lockingContractAddress}`);
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Disambiguate the getConfig() and getBlockchains() return shapes.

Line 60 groups both methods together, but Lines 63-70 only show the getConfig() envelope (config.blockchains). Elsewhere the docs show getBlockchains() returning the array directly, so this wording makes it easy to copy the wrong access pattern. Either split the examples or state explicitly that getBlockchains() already returns the array.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/build/sdk/typescript/configuration.mdx` around lines 60 - 70, The docs
currently conflate the return shapes of getConfig() and getBlockchains(); update
the text and examples to disambiguate by showing two short examples: one that
calls getConfig() and accesses the array via config.blockchains (e.g., const
config = await client.getConfig(); for (const chain of config.blockchains) { ...
}) and a second that calls getBlockchains() which returns the array directly
(e.g., const blockchains = await client.getBlockchains(); for (const chain of
blockchains) { ... }), and/or add a single clarifying sentence explicitly
stating that getBlockchains() returns the blockchain array while getConfig()
returns an envelope object with a blockchains property.

Comment on lines +358 to +391
async function lockAndRegisterApp() {
const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
const client = await Client.create(
process.env.WS_URL!,
stateSigner,
txSigner,
withBlockchainRPC(11155111n, process.env.SEPOLIA_RPC!),
);

const chainId = 11155111n;
const lockAmount = new Decimal(100);

// Approve the locking contract to spend tokens
await client.approveSecurityToken(chainId, lockAmount);

// Lock tokens for yourself
const userAddress = client.getUserAddress();
await client.escrowSecurityTokens(userAddress, chainId, lockAmount);

// Check locked balance
const balance = await client.getLockedBalance(chainId, userAddress);
console.log('Locked balance:', balance.toString());

// Register an app (requires locked tokens)
await client.registerApp('my-app', '{"name": "My App", "description": "Demo"}', false);
console.log('App registered');

// Later: initiate unlock
// await client.initiateSecurityTokensWithdrawal(chainId);

// After unlock period: withdraw
// await client.withdrawSecurityTokens(chainId, userAddress);

await client.close();
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Close the client in a finally block.

Unlike the other examples in this file, this snippet only calls close() on the success path. Any failure during approval, escrow, balance lookup, or app registration leaves the WebSocket open in the copied example.

♻️ Proposed fix
 async function lockAndRegisterApp() {
   const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
   const client = await Client.create(
     process.env.WS_URL!,
     stateSigner,
     txSigner,
     withBlockchainRPC(11155111n, process.env.SEPOLIA_RPC!),
   );
 
   const chainId = 11155111n;
   const lockAmount = new Decimal(100);
 
-  // Approve the locking contract to spend tokens
-  await client.approveSecurityToken(chainId, lockAmount);
-
-  // Lock tokens for yourself
-  const userAddress = client.getUserAddress();
-  await client.escrowSecurityTokens(userAddress, chainId, lockAmount);
-
-  // Check locked balance
-  const balance = await client.getLockedBalance(chainId, userAddress);
-  console.log('Locked balance:', balance.toString());
-
-  // Register an app (requires locked tokens)
-  await client.registerApp('my-app', '{"name": "My App", "description": "Demo"}', false);
-  console.log('App registered');
-
-  // Later: initiate unlock
-  // await client.initiateSecurityTokensWithdrawal(chainId);
-
-  // After unlock period: withdraw
-  // await client.withdrawSecurityTokens(chainId, userAddress);
-
-  await client.close();
+  try {
+    // Approve the locking contract to spend tokens
+    await client.approveSecurityToken(chainId, lockAmount);
+
+    // Lock tokens for yourself
+    const userAddress = client.getUserAddress();
+    await client.escrowSecurityTokens(userAddress, chainId, lockAmount);
+
+    // Check locked balance
+    const balance = await client.getLockedBalance(chainId, userAddress);
+    console.log('Locked balance:', balance.toString());
+
+    // Register an app (requires locked tokens)
+    await client.registerApp('my-app', '{"name": "My App", "description": "Demo"}', false);
+    console.log('App registered');
+
+    // Later: initiate unlock
+    // await client.initiateSecurityTokensWithdrawal(chainId);
+
+    // After unlock period: withdraw
+    // await client.withdrawSecurityTokens(chainId, userAddress);
+  } finally {
+    await client.close();
+  }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
async function lockAndRegisterApp() {
const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
const client = await Client.create(
process.env.WS_URL!,
stateSigner,
txSigner,
withBlockchainRPC(11155111n, process.env.SEPOLIA_RPC!),
);
const chainId = 11155111n;
const lockAmount = new Decimal(100);
// Approve the locking contract to spend tokens
await client.approveSecurityToken(chainId, lockAmount);
// Lock tokens for yourself
const userAddress = client.getUserAddress();
await client.escrowSecurityTokens(userAddress, chainId, lockAmount);
// Check locked balance
const balance = await client.getLockedBalance(chainId, userAddress);
console.log('Locked balance:', balance.toString());
// Register an app (requires locked tokens)
await client.registerApp('my-app', '{"name": "My App", "description": "Demo"}', false);
console.log('App registered');
// Later: initiate unlock
// await client.initiateSecurityTokensWithdrawal(chainId);
// After unlock period: withdraw
// await client.withdrawSecurityTokens(chainId, userAddress);
await client.close();
async function lockAndRegisterApp() {
const { stateSigner, txSigner } = createSigners(process.env.PRIVATE_KEY!);
const client = await Client.create(
process.env.WS_URL!,
stateSigner,
txSigner,
withBlockchainRPC(11155111n, process.env.SEPOLIA_RPC!),
);
const chainId = 11155111n;
const lockAmount = new Decimal(100);
try {
// Approve the locking contract to spend tokens
await client.approveSecurityToken(chainId, lockAmount);
// Lock tokens for yourself
const userAddress = client.getUserAddress();
await client.escrowSecurityTokens(userAddress, chainId, lockAmount);
// Check locked balance
const balance = await client.getLockedBalance(chainId, userAddress);
console.log('Locked balance:', balance.toString());
// Register an app (requires locked tokens)
await client.registerApp('my-app', '{"name": "My App", "description": "Demo"}', false);
console.log('App registered');
// Later: initiate unlock
// await client.initiateSecurityTokensWithdrawal(chainId);
// After unlock period: withdraw
// await client.withdrawSecurityTokens(chainId, userAddress);
} finally {
await client.close();
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/build/sdk/typescript/examples.mdx` around lines 358 - 391, The example
function lockAndRegisterApp currently calls client.close() only on the success
path; wrap the main flow in a try/finally so the WebSocket client is always
closed: declare the client variable outside the try, assign it via
Client.create(...) inside the try, perform approveSecurityToken,
escrowSecurityTokens, getLockedBalance, and registerApp inside the try, and call
await client.close() in the finally (checking the client is non-null) to
guarantee cleanup even on errors.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants