Lighter.Signer.Net 0.1.0

dotnet add package Lighter.Signer.Net --version 0.1.0
                    
NuGet\Install-Package Lighter.Signer.Net -Version 0.1.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Lighter.Signer.Net" Version="0.1.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Lighter.Signer.Net" Version="0.1.0" />
                    
Directory.Packages.props
<PackageReference Include="Lighter.Signer.Net" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Lighter.Signer.Net --version 0.1.0
                    
#r "nuget: Lighter.Signer.Net, 0.1.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Lighter.Signer.Net@0.1.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Lighter.Signer.Net&version=0.1.0
                    
Install as a Cake Addin
#tool nuget:?package=Lighter.Signer.Net&version=0.1.0
                    
Install as a Cake Tool

Lighter.Signer.Net

CI .NET 8 and 10 License: MIT

A fully managed, dependency-free .NET signer for Lighter authentication tokens and transactions.

Lighter.Signer.Net implements the Goldilocks, Poseidon2, ECgFp5, and Schnorr signing path in C#. It accepts prepared transaction parameters and returns payloads ready for submission to the exchange. This is an unofficial community project and is not affiliated with Lighter.

At a glance

Property Value
Supported operations Authentication, create order, modify order, cancel order, update leverage, approve integrator, sub-account transfer, L2 transaction attributes
Implementation Fully managed C#; no native libraries
Package dependencies None
Target frameworks .NET 8 and .NET 10; compatible with .NET 9 via the .NET 8 asset
Package status Preview

Installation

dotnet add package Lighter.Signer.Net --version 0.2.0-preview.1

To install a package built from this repository:

dotnet pack src/Lighter.Signer.Net/Lighter.Signer.Net.csproj -c Release -o artifacts
dotnet add package Lighter.Signer.Net --version 0.2.0-preview.1 --source artifacts

Quick start

using Lighter.Signer;
using Lighter.Signer.Transactions;

var privateKey = Environment.GetEnvironmentVariable("LIGHTER_PRIVATE_KEY")
    ?? throw new InvalidOperationException("LIGHTER_PRIVATE_KEY is required.");

var signer = new LighterSigner(
    privateKeyHex: privateKey,
    accountIndex: 123,
    apiKeyIndex: 0,
    chainId: 304);

var authToken = signer.CreateAuthToken(DateTimeOffset.UtcNow.AddMinutes(10));

var signedOrder = signer.SignCreateOrder(
    new OrderRequest(
        MarketIndex: 7,
        ClientOrderIndex: 123456,
        BaseAmount: 20_000_000,
        Price: 1_000_000,
        IsAsk: false,
        Type: 0,
        TimeInForce: 1,
        ReduceOnly: false,
        TriggerPrice: 0,
        OrderExpiry: LighterSigner.Default28DayOrderExpiry),
    nonce: 42);

// Submit signedOrder.TransactionType and signedOrder.TransactionInfo
// through your application's Lighter API client.

The values above are illustrative. Amounts and prices must be scaled using the target market's supported decimal precision.

OrderRequest takes raw byte fields, so consumers can plug in their own models. The OrderType, OrderTimeInForce, SelfTradeBehavior, SelfTradeEquality, and MarginMode enums are optional conveniences; OrderRequest.Create(...) accepts the enums directly:

var order = OrderRequest.Create(
    marketIndex: 7,
    clientOrderIndex: 123456,
    baseAmount: 20_000_000,
    price: 1_000_000,
    isAsk: false,
    type: OrderType.Limit,
    timeInForce: OrderTimeInForce.GoodTillTime,
    reduceOnly: false,
    triggerPrice: 0,
    orderExpiry: LighterSigner.Default28DayOrderExpiry);

An OrderExpiry of -1 (LighterSigner.Default28DayOrderExpiry) signs the order with a 28-day expiry, matching the official signers. All order types are supported — limit, market, stop-loss, stop-loss limit, take-profit, take-profit limit, and TWAP — with the same per-type validation rules as the Go signer; spot markets accept limit, market, and TWAP orders, while trigger orders and reduce-only are perpetual-market-only.

Supported operations

Method Result
CreateAuthToken(deadline) Time-limited authentication token
SignCreateOrder(order, nonce, attributes?) Signed create-order transaction
SignModifyOrder(modify, nonce, attributes?) Signed modify-order transaction
SignCancelOrder(marketIndex, exchangeOrderIndex, nonce, attributes?) Signed cancel-order transaction
SignUpdateLeverage(marketIndex, initialMarginFraction, marginMode, nonce, attributes?) Signed update-leverage transaction
SignApproveIntegrator(approval, nonce, attributes?) Signed approve-integrator transaction
SignTransfer(transfer, nonce, attributes?) Signed sub-account transfer transaction

Each transaction-signing method returns a SignedTransaction containing:

  • TransactionType — Lighter transaction type identifier.
  • TransactionInfo — serialized signed payload for submission.
  • TransactionHash — hexadecimal hash of the signed transaction fields.
  • L1SignatureBody — for approve-integrator transactions, the human-readable message an account's L1 (Ethereum) key signs to authorize the approval; null otherwise.

Approving a third-party integrator with non-zero fees also needs that message signed by the account's Ethereum key as an EIP-191 personal message. The library is dependency-free and does not sign with Ethereum keys, so sign L1SignatureBody with your own tooling and attach the result. Matching the official Python SDK, WithL1Signature patches the signature into the payload's L1Sig field and leaves the transaction hash untouched:

SignedTransaction approval = signer.SignApproveIntegrator(new ApproveIntegratorRequest(6, 1_000, 1_000, 1_000, 1_000, approvalExpiry), nonce);
string l1Signature = SignPersonalMessage(approval.L1SignatureBody!); // 0x-prefixed 65-byte hex from your Ethereum signer
SignedTransaction ready = approval.WithL1Signature(l1Signature);

Approvals of a sub-account under the same master account, zero-fee approvals, and revocations (approval expiry 0) are submitted without an L1 signature, exactly as the official SDKs do.

The transfer memo is a string carrying exactly 32 bytes: 32 raw characters, or 64 hex characters (optionally 0x-prefixed). Matching the official signers, shorter memos are not padded automatically.

The signer expects prepared inputs, including the correct chain ID, nonce, scaled market values, and exchange order index. Retrieving those values and submitting the resulting payload are responsibilities of the calling application. ExchangeConstants exposes the exchange's protocol bounds (market index ranges, order index limits, fee tick, and so on) for client-side validation.

L2 transaction attributes

Every transaction-signing method accepts an optional L2TxAttributes for integrator fees, nonce skipping, self-trade behavior, and modify-order versions. Set only the fields you need — at most four per transaction — and leave the rest null:

var signedWithAttributes = signer.SignCreateOrder(order, nonce, new L2TxAttributes
{
    SelfTradeBehaviorMode = (byte)SelfTradeBehavior.CancelBoth,
});

Attributes at their default values (for example a fee of 0) appear in the payload but, matching the Go signer, do not change the transaction hash.

OrderVersion mirrors the Python SDK's order_version for modify orders. The exchange applies a versioned modify only when the version is greater than the order's current one, so stale or retried modifies cannot overwrite a newer one. A millisecond timestamp is the usual choice:

SignedTransaction versioned = signer.SignModifyOrder(modify, nonce, new L2TxAttributes
{
    OrderVersion = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
});

Transaction expiry

Signed transactions expire LighterSigner.DefaultTransactionExpiry (ten minutes less a second) after signing. Adjust it per signer instance:

signer.TransactionExpiry = TimeSpan.FromMinutes(5);

Security

  • Never commit, print, or transmit private keys outside the intended signing environment.
  • Treat authentication tokens and signed payloads as sensitive data.
  • Validate chain IDs, nonces, amounts, prices, destination accounts, and expiry times before signing.
  • Keep transaction submission and error handling separate from signing.

Live sample

The console sample submits real transactions. Review its constants and target endpoint before running it.

The non-packaged sample demonstrates an end-to-end REST workflow. It retrieves account data and a nonce, submits a 20 XRP limit buy at $1 to satisfy the exchange minimum, confirms the order is open, cancels it, and confirms its removal.

Create an uncommitted APIKEY file in the repository root:

Public Key: XXX
Private Key: XXX
Account Index: XXX

L1 Address: XXX
Key Index: XXX

Then run:

dotnet run --project samples/Lighter.Signer.Net.Console/Lighter.Signer.Net.Console.csproj -c Release -f net10.0

The sample's REST client, credential reader, endpoint discovery, and trading workflow are not included in the NuGet package. Its outgoing logs redact credential-derived fields and signatures. The APIKEY file is ignored by source control and must never be committed.

Repository layout

src/Lighter.Signer.Net/                 Signer library and NuGet package
samples/Lighter.Signer.Net.Console/     Non-packaged live REST sample
tests/Lighter.Signer.Net.Tests/         Cryptographic, transaction, REST, and workflow tests

Build and test

dotnet build Lighter.Signer.Net.sln -c Release
dotnet run --project tests/Lighter.Signer.Net.Tests/Lighter.Signer.Net.Tests.csproj -c Release -f net8.0
dotnet run --project tests/Lighter.Signer.Net.Tests/Lighter.Signer.Net.Tests.csproj -c Release -f net10.0
dotnet pack src/Lighter.Signer.Net/Lighter.Signer.Net.csproj -c Release -o artifacts

The test suite includes official cryptographic vectors, transaction hashes generated by the official Go signer, REST wire-contract checks, and the complete place/list/cancel workflow against a stateful fake exchange.

References

License

Licensed under the MIT License.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net10.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.1.0 368 9/11/2026
0.1.0-preview.1 85 8/7/2026