@gvnrdao/dh-sdk 0.0.235 → 0.0.243

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/constants/chunks/deployment-addresses.d.ts +2 -0
  2. package/dist/constants/chunks/network-configs.d.ts +2 -0
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js +20474 -31322
  5. package/dist/index.mjs +20305 -31155
  6. package/dist/interfaces/chunks/config.i.d.ts +20 -10
  7. package/dist/interfaces/chunks/contract-interactions.i.d.ts +2 -2
  8. package/dist/interfaces/chunks/contract-types.i.d.ts +95 -91
  9. package/dist/interfaces/chunks/loan-operations.i.d.ts +2 -3
  10. package/dist/modules/bitcoin/bitcoin-operations.module.d.ts +37 -0
  11. package/dist/modules/cache/cache-manager.module.d.ts +8 -0
  12. package/dist/modules/contract/contract-manager.module.d.ts +5 -5
  13. package/dist/modules/diamond-hands-sdk.d.ts +103 -7
  14. package/dist/modules/loan/loan-creator.module.d.ts +1 -1
  15. package/dist/modules/loan/loan-query.module.d.ts +3 -3
  16. package/dist/modules/pkp/pkp-manager.module.d.ts +6 -2
  17. package/dist/protocol/protocol-pause.d.ts +2 -2
  18. package/dist/utils/address-conversion.utils.d.ts +39 -0
  19. package/dist/utils/bitcoin-provider.utils.d.ts +36 -0
  20. package/dist/utils/btc-withdrawal-message.d.ts +60 -0
  21. package/dist/utils/chunks/bitcoin-utils.d.ts +10 -0
  22. package/dist/utils/chunks/eip1559-broadcast.utils.d.ts +8 -9
  23. package/dist/utils/eip712-login.d.ts +27 -0
  24. package/dist/utils/extend-authorization.utils.d.ts +2 -2
  25. package/dist/utils/mint-authorization.utils.d.ts +9 -8
  26. package/dist/utils/position-delegate.utils.d.ts +41 -0
  27. package/dist/utils/server-session.d.ts +44 -0
  28. package/dist/utils/signature-tempering.utils.d.ts +6 -3
  29. package/package.json +6 -7
  30. package/dist/utils/bitcoin-signature.d.ts +0 -20
@@ -70,8 +70,72 @@ export declare class DiamondHandsSDK {
70
70
  private readonly bitcoinOperations;
71
71
  private readonly mockTokenManager?;
72
72
  private readonly graphClient;
73
+ /**
74
+ * Session helper for the lit-ops-server. Set in service mode; undefined
75
+ * in standalone mode (no server to authenticate against). Use
76
+ * `this.getAuthHeader()` which centralizes the undefined check.
77
+ */
78
+ private readonly serverSession?;
73
79
  private isInitialized;
74
80
  private isDisposed;
81
+ /**
82
+ * Audit H-13: per-position write serialization. Tracks positions with an
83
+ * in-flight state-mutating call so a concurrent mint / payment / extend /
84
+ * withdraw / liquidation for the same position fast-fails locally instead
85
+ * of paying a full Lit-Action round-trip + gas only to revert on-chain
86
+ * via the M-4 flash-loan protection's `lastInteractionBlockByPosition`
87
+ * guard. Stored as a Set — no Promise needed since callers don't await
88
+ * on each other; they get an immediate refusal and can retry once their
89
+ * sibling call has completed.
90
+ */
91
+ private readonly inFlightWrites;
92
+ /**
93
+ * Acquire the per-position write lock. Returns `null` on success, or a
94
+ * structured failure when another write is already in flight. The caller
95
+ * must `cast` the failure to the method's specific result type — every
96
+ * write-method result includes a `{ success: false; error: string }`
97
+ * branch so the cast is safe.
98
+ */
99
+ private tryAcquireWriteLock;
100
+ /** Release the per-position write lock. Safe to call when not held. */
101
+ private releaseWriteLock;
102
+ /**
103
+ * Build the `Authorization: Bearer <jwt>` header for a request to
104
+ * lit-ops-server. Returns an empty object in standalone mode (no server
105
+ * to authenticate to) or when the session helper has not been wired —
106
+ * in which case the server's `requireSessionToken` middleware will
107
+ * reject the call with 401, which is the correct outcome.
108
+ */
109
+ private getAuthHeader;
110
+ /**
111
+ * Audit H-9: invalidate the LoanQuery cache so subsequent reads return
112
+ * the post-write state. We clear the entire loan-query cache (not just
113
+ * the entry for this position) because the cache keys by `pkpId` and we
114
+ * don't always have it in scope at the release site — a position-keyed
115
+ * helper would require a pre-write lookup that defeats the cache. The
116
+ * blast radius is bounded: the cache is per-process and a fresh fetch
117
+ * is cheap relative to a Lit Action call.
118
+ *
119
+ * `includePkpCache: true` is passed by liquidation to also drop the
120
+ * 24-hour PKP-data cache entry — the Lit auth-context attached to a
121
+ * PKP changes when ownership transfers, so the cached `ethAddress`
122
+ * (used for capacity-credit delegation) must be re-derived.
123
+ */
124
+ private invalidateCachesForPosition;
125
+ /**
126
+ * Audit H-11: pre-flight check for `PositionManager.getProtocolPauseStatus()`.
127
+ *
128
+ * Returns `{ ok: true }` if none of the supplied pause keys are set, or
129
+ * `{ ok: false, error }` if the protocol is paused for this operation
130
+ * type. Caller returns the structured failure to the user before paying
131
+ * for a LIT Action round-trip + gas that the on-chain function would
132
+ * later revert.
133
+ *
134
+ * Best-effort: if no EVM provider is available (e.g., service-mode setup
135
+ * without `ethRpcUrl`) or the read itself fails, we return `{ ok: true }`
136
+ * with a debug log — the on-chain call remains the final authority.
137
+ */
138
+ private preflightProtocolPause;
75
139
  /**
76
140
  * Private constructor - use DiamondHandsSDK.create() instead
77
141
  *
@@ -328,7 +392,7 @@ export declare class DiamondHandsSDK {
328
392
  * @param customBitcoinRpcUrl - Optional custom Bitcoin RPC URL (for local testing)
329
393
  * @returns Withdrawal result with transaction details
330
394
  */
331
- withdrawBTC(positionId: string, withdrawalAddress: string, withdrawalAmount: number, rpcUrl?: string, customBitcoinRpcUrl?: string): Promise<BTCWithdrawalResult>;
395
+ withdrawBTC(positionId: string, withdrawalAddress: string, withdrawalAmount: number): Promise<BTCWithdrawalResult>;
332
396
  /**
333
397
  * Execute Bitcoin withdrawal (Phase 2)
334
398
  *
@@ -341,10 +405,15 @@ export declare class DiamondHandsSDK {
341
405
  executeBTCWithdrawal(request: {
342
406
  positionId: string;
343
407
  utxoIdentifier: string;
408
+ utxoSatoshis: number;
344
409
  networkFee: number;
345
410
  destination: string;
346
- rpcUrl?: string;
347
- customBitcoinRpcUrl?: string;
411
+ /**
412
+ * User-authorized withdrawal amount in satoshis (Phase 1 `withdrawalAmount`).
413
+ * Bound into the Phase-2 signature alongside `destination` so the Lit
414
+ * Action can cross-check against the on-chain authorizer record.
415
+ */
416
+ targetAmount: number;
348
417
  }): Promise<{
349
418
  success: boolean;
350
419
  txid?: string;
@@ -364,7 +433,7 @@ export declare class DiamondHandsSDK {
364
433
  * @param rpcUrl - Optional RPC URL override for LIT Action (for local testing)
365
434
  * @returns Array of execution results for each pending transfer
366
435
  */
367
- executePendingBtcTransfers(positionId: string, networkFee: number, rpcUrl?: string): Promise<Array<{
436
+ executePendingBtcTransfers(positionId: string, networkFee: number): Promise<Array<{
368
437
  success: boolean;
369
438
  utxoIdentifier?: string;
370
439
  txid?: string;
@@ -423,7 +492,7 @@ export declare class DiamondHandsSDK {
423
492
  * @param customBitcoinRpcUrl - Optional custom Bitcoin RPC URL (for local testing)
424
493
  * @returns Complete withdrawal result with both authorization and execution details
425
494
  */
426
- withdrawBTCAndExecute(positionId: string, withdrawalAddress: string, withdrawalAmount: number, networkFee: number, rpcUrl?: string, customBitcoinRpcUrl?: string): Promise<{
495
+ withdrawBTCAndExecute(positionId: string, withdrawalAddress: string, withdrawalAmount: number, networkFee: number): Promise<{
427
496
  success: boolean;
428
497
  authorization?: BTCWithdrawalResult;
429
498
  transfers?: Array<{
@@ -463,7 +532,7 @@ export declare class DiamondHandsSDK {
463
532
  getLoansByBorrower(borrower: string, pagination?: {
464
533
  page: number;
465
534
  pageSize: number;
466
- }): Promise<Result<import("../interfaces/chunks/loan-operations.i").PaginatedLoansResponse, SDKError>>;
535
+ }, orderBy?: "createdAt" | "lastUpdatedAt" | "ucdDebt", orderDirection?: "asc" | "desc"): Promise<Result<import("../interfaces/chunks/loan-operations.i").PaginatedLoansResponse, SDKError>>;
467
536
  /**
468
537
  * Get all active loans
469
538
  *
@@ -524,6 +593,13 @@ export declare class DiamondHandsSDK {
524
593
  * @returns the current Bitcoin price in USD
525
594
  */
526
595
  getBitcoinPrice(): Promise<{
596
+ price: number;
597
+ priceE8: string;
598
+ timestamp: number;
599
+ source: string;
600
+ signature?: undefined;
601
+ signer?: undefined;
602
+ } | {
527
603
  price: number;
528
604
  priceE8: string;
529
605
  timestamp: number;
@@ -571,6 +647,23 @@ export declare class DiamondHandsSDK {
571
647
  * ```
572
648
  */
573
649
  getTermsWithFees(): Promise<Result<TermsWithFeesResult, SDKError>>;
650
+ getProtocolConfig(): Promise<Result<{
651
+ liquidationThreshold: string;
652
+ minimumLoanValueUcd: string;
653
+ minimumLoanValueWei: string;
654
+ maxSingleLoanValueUcd: string;
655
+ maxSingleLoanValueWei: string;
656
+ }, SDKError>>;
657
+ getGasBalance(address: string): Promise<Result<{
658
+ balanceWei: string;
659
+ balanceEth: string;
660
+ }, SDKError>>;
661
+ getVaultBalance(positionId: string): Promise<Result<{
662
+ vaultAddress: string;
663
+ balanceSats: string;
664
+ balanceBtc: string;
665
+ btcPrice: string;
666
+ }, SDKError>>;
574
667
  /**
575
668
  * Mint mock BTC tokens (test networks only)
576
669
  *
@@ -612,7 +705,10 @@ export declare class DiamondHandsSDK {
612
705
  */
613
706
  private isProductionNetwork;
614
707
  /**
615
- * Get Bitcoin network based on chain
708
+ * Get Bitcoin network based on chain.
709
+ *
710
+ * Provider URLs are now sourced from the on-chain registry, so the network
711
+ * is derived purely from `this.config.chain`.
616
712
  */
617
713
  private getBitcoinNetwork;
618
714
  /**
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * Flow: PKP Creation → Authorization → Contract Call → Verification
12
12
  */
13
- import type { Wallet } from "ethers";
13
+ import { type Wallet } from "ethers";
14
14
  import { Result } from "../../types/result";
15
15
  import { SDKError } from "../../utils/error-handler";
16
16
  import type { PKPManager } from "../pkp/pkp-manager.module";
@@ -16,7 +16,7 @@ import type { Cache } from "../cache/cache-manager.module";
16
16
  import type { LoanData, LoanDataDetail, PaginatedLoansResponse } from "../../interfaces/chunks/loan-operations.i";
17
17
  import type { LoanEvents, LoanEventsFilter } from "../../types/event-types";
18
18
  import { DiamondHandsGraphClient } from "@graphs/diamond-hands";
19
- import type { providers } from "ethers";
19
+ import { type Provider } from "ethers";
20
20
  /**
21
21
  * Loan query filters
22
22
  */
@@ -52,7 +52,7 @@ export interface LoanQueryConfig {
52
52
  /** Bitcoin operations for balance enrichment */
53
53
  bitcoinOperations: BitcoinOperations;
54
54
  /** Ethereum provider for PKP public key retrieval */
55
- provider?: providers.Provider;
55
+ provider?: Provider;
56
56
  /** PositionManagerCoreModule address — used as fallback vault address source for Chipotle loans */
57
57
  positionManagerCoreAddress?: string;
58
58
  /** Cache for loan query results (keyed by PKP ID) */
@@ -132,7 +132,7 @@ export declare class LoanQuery {
132
132
  * @param pagination - Pagination parameters
133
133
  * @returns Paginated loans for borrower
134
134
  */
135
- getLoansByBorrower(borrower: string, pagination?: PaginationParams): Promise<Result<PaginatedLoansResponse, SDKError>>;
135
+ getLoansByBorrower(borrower: string, pagination?: PaginationParams, orderBy?: "createdAt" | "lastUpdatedAt" | "ucdDebt", orderDirection?: "asc" | "desc"): Promise<Result<PaginatedLoansResponse, SDKError>>;
136
136
  /**
137
137
  * Get active loans (status = 0)
138
138
  *
@@ -27,8 +27,12 @@ export interface PKPManagerConfig {
27
27
  litNetwork: string;
28
28
  /** Service mode: endpoint for lit-ops-server */
29
29
  serviceEndpoint?: string;
30
- /** Service mode: authentication token */
31
- serviceAuthToken?: string;
30
+ /**
31
+ * Service mode: returns `Authorization`-style headers for each request.
32
+ * Called once per request so the underlying session can refresh as
33
+ * needed. Empty object disables the header (server will 401).
34
+ */
35
+ getAuthHeader?: () => Promise<Record<string, string>>;
32
36
  /** Direct mode: wallet for PKP operations */
33
37
  litOpsWallet?: Wallet;
34
38
  /** Optional cache for PKP data */
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Helpers for `PositionManager.getProtocolPauseStatus()` (Lit Actions / client fast-fail).
3
3
  */
4
- import { ethers } from 'ethers';
4
+ import { type Provider } from 'ethers';
5
5
  export type ProtocolPauseStatus = {
6
6
  positionManagerPaused: boolean;
7
7
  positionManagerLiquidationsPaused: boolean;
@@ -14,6 +14,6 @@ export type ProtocolPauseStatus = {
14
14
  ucdTokenPaused: boolean;
15
15
  simplePsmPaused: boolean;
16
16
  };
17
- export declare function fetchProtocolPauseStatus(provider: ethers.providers.Provider, positionManagerAddress: string): Promise<ProtocolPauseStatus>;
17
+ export declare function fetchProtocolPauseStatus(provider: Provider, positionManagerAddress: string): Promise<ProtocolPauseStatus>;
18
18
  export type ProtocolPauseKey = keyof ProtocolPauseStatus;
19
19
  export declare function assertProtocolNotPaused(status: ProtocolPauseStatus, requiredKeys: readonly ProtocolPauseKey[]): void;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Address Conversion Utilities
3
+ * Provides safe address conversion and validation with clear error messages
4
+ */
5
+ /**
6
+ * Safely convert a string to bytes32 with clear error handling
7
+ * @param value String value to convert
8
+ * @param fieldName Name of the field for error messages
9
+ * @returns bytes32 string
10
+ * @throws Clear error message if conversion fails
11
+ */
12
+ export declare function safeHexZeroPad(value: string, fieldName?: string): string;
13
+ /**
14
+ * Safely get Bitcoin addresses from PKP with retry and clear error handling
15
+ * @param pkpId PKP ID to derive addresses from
16
+ * @param maxRetries Maximum number of retries (default: 3)
17
+ * @returns Bitcoin addresses for all networks
18
+ * @throws Clear error message if derivation fails
19
+ */
20
+ export declare function safeGetBitcoinAddressesFromPkp(pkpId: string, maxRetries?: number): Promise<{
21
+ mainnet: string;
22
+ testnet: string;
23
+ regtest: string;
24
+ }>;
25
+ /**
26
+ * Safely validate and format a Bitcoin address
27
+ * @param address Bitcoin address to validate
28
+ * @param network Network type for validation
29
+ * @returns Validated address
30
+ * @throws Clear error message if validation fails
31
+ */
32
+ export declare function safeValidateBitcoinAddress(address: string, network?: 'mainnet' | 'testnet' | 'regtest'): string;
33
+ /**
34
+ * Safely parse and validate a position ID
35
+ * @param positionId Position ID to validate
36
+ * @returns Validated position ID
37
+ * @throws Clear error message if validation fails
38
+ */
39
+ export declare function safeValidatePositionId(positionId: string): string;
@@ -45,4 +45,40 @@ export declare class BitcoinProvider {
45
45
  * Check if an address has received at least a specific amount
46
46
  */
47
47
  hasReceivedAmount(address: string, expectedAmount: bigint): Promise<boolean>;
48
+ /**
49
+ * Fetch a Bitcoin transaction by txid.
50
+ *
51
+ * Audit CRIT-2: used to verify that a Phase-2 BTC withdrawal the server
52
+ * claimed broadcast actually exists and matches the user's authorization.
53
+ * Returns `null` if no provider has the tx yet — the caller may retry to
54
+ * allow for propagation/indexing delay.
55
+ *
56
+ * Esplora response shape: `{ txid, vin: [{txid, vout, ...}], vout: [{value, scriptpubkey_address, ...}], status: {confirmed, ...} }`
57
+ */
58
+ getTransaction(txid: string): Promise<BitcoinTransactionInfo | null>;
59
+ /**
60
+ * Try each candidate path on the provider. Returns `null` on 404 (tx not
61
+ * yet visible) but throws on other errors so the outer loop can move to
62
+ * the next provider.
63
+ */
64
+ private fetchTxFromProvider;
65
+ }
66
+ /**
67
+ * Normalized Bitcoin transaction information returned by `getTransaction`.
68
+ * Only the fields used by post-broadcast verification are populated; we
69
+ * deliberately do NOT echo full witness / scriptpubkey data to keep the
70
+ * surface small.
71
+ */
72
+ export interface BitcoinTransactionInfo {
73
+ txid: string;
74
+ vin: Array<{
75
+ txid: string;
76
+ vout: number;
77
+ }>;
78
+ vout: Array<{
79
+ value: number;
80
+ address?: string;
81
+ }>;
82
+ /** True if the tx is in a block, false if still in mempool, undefined unknown. */
83
+ confirmed?: boolean;
48
84
  }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Helpers for building the EIP-191 `execute-btc-withdrawal` envelope that the
3
+ * `btc-transaction-signer` LIT Action verifies.
4
+ *
5
+ * Pulled out of the CLI's executePendingWithdrawal util so the SDK and CLI
6
+ * use the same logic and signing rules.
7
+ */
8
+ import { type Signer } from "ethers";
9
+ export interface BtcExecuteSignParams {
10
+ positionId: string;
11
+ txid: string;
12
+ vout: number;
13
+ networkFee: number;
14
+ chainId: number;
15
+ signer: Signer;
16
+ }
17
+ export interface BtcExecuteSignedEnvelope {
18
+ positionId: string;
19
+ txid: string;
20
+ vout: number;
21
+ satoshis: number;
22
+ /** Bitcoin destination address bound into the signature. */
23
+ targetAddress: string;
24
+ /** Authorized withdrawal amount (sats) bound into the signature. */
25
+ targetAmount: number;
26
+ networkFee: number;
27
+ chainId: number;
28
+ /** Quantum-aligned timestamp (start of a 60s quantum). */
29
+ timestamp: number;
30
+ /** EIP-191 signature over the message hash. */
31
+ userSignature: string;
32
+ /** Address recovered from the signer (borrower). */
33
+ borrowerAddress: string;
34
+ }
35
+ /**
36
+ * Build the quantum-aligned timestamp + EIP-191 signature the
37
+ * `/api/lit/pending-withdrawals/execute` endpoint expects.
38
+ *
39
+ * Audit CRIT-1: the signed message now binds `targetAddress` and `targetAmount`
40
+ * in addition to the UTXO identifier. The previous shape bound only the UTXO,
41
+ * delegating destination/amount enforcement to the Lit Action's on-chain
42
+ * `getAuthorizedSpends` lookup. That single defense was reliable in practice
43
+ * but the user-signed message is now self-describing — the Lit Action
44
+ * cross-checks the user-signed values against the on-chain authorizer record
45
+ * and refuses any disagreement, so a bug or future loosening of one side does
46
+ * not silently redirect funds.
47
+ *
48
+ * Caller passes the UTXO satoshis (from Phase 1 result) AND the user-authorized
49
+ * destination + amount; this helper returns everything the server needs to
50
+ * delegate to the BTC signer LIT Action.
51
+ *
52
+ * Wire-compat: this is a coordinated breaking change — the new SDK signatures
53
+ * are not accepted by an older btc-transaction-signer Lit Action, and the new
54
+ * Lit Action does not accept older SDK signatures. Deploy together.
55
+ */
56
+ export declare function buildBtcExecuteEnvelope(params: BtcExecuteSignParams & {
57
+ satoshis: number;
58
+ targetAddress: string;
59
+ targetAmount: number;
60
+ }): Promise<BtcExecuteSignedEnvelope>;
@@ -51,6 +51,16 @@ export declare function getBitcoinAddressFromPkp(pkpPublicKey: string, network?:
51
51
  */
52
52
  export declare function getBitcoinAddressesFromPkp(pkpPublicKey: string): Promise<BitcoinAddresses>;
53
53
  export declare class BitcoinUtils {
54
+ /**
55
+ * Validate a Bitcoin address across mainnet / testnet / regtest with full
56
+ * checksum verification.
57
+ *
58
+ * Audit H-12: the previous implementation was a permissive regex with no
59
+ * checksum check — garbage like `bc1qqqqqqqqqq` passed. The new
60
+ * implementation uses the `bech32` and `bs58check` packages (both already
61
+ * in deps) to validate the actual checksum, and rejects unknown HRPs /
62
+ * version bytes / witness program lengths.
63
+ */
54
64
  static validateAddress(address: string): boolean;
55
65
  static formatTransaction(hash: string, amount: string, recipient: string): {
56
66
  hash: string;
@@ -2,23 +2,22 @@
2
2
  * EIP-1559 transaction broadcast helpers for paths that need explicit gas limits
3
3
  * (e.g. large mintUCD) without manual signDigest / eth_sendRawTransaction.
4
4
  */
5
- import { ethers as ethers5 } from "ethers";
6
- import type { BigNumber, providers, Signer } from "ethers";
5
+ import { type Provider, type Signer, type TransactionResponse } from "ethers";
7
6
  /** Observed mintUCD + LIT validation can exceed 7M gas; cap avoids block limit issues. */
8
- export declare const MINT_UCD_GAS_CEILING: ethers5.BigNumber;
7
+ export declare const MINT_UCD_GAS_CEILING: bigint;
9
8
  /** Headroom on eth_estimateGas (25%). */
10
9
  export declare const MINT_UCD_ESTIMATE_MARGIN_BPS = 2500;
11
10
  /**
12
11
  * Returns gas limit with margin, capped, or null if estimateGas reverts/fails.
13
12
  */
14
- export declare function estimateContractCallGasWithMargin(provider: providers.Provider, from: string, to: string, data: string, marginBps: number, ceiling: BigNumber): Promise<BigNumber | null>;
15
- export declare function resolveEip1559FeeFields(provider: providers.Provider): Promise<{
16
- maxFeePerGas: BigNumber;
17
- maxPriorityFeePerGas: BigNumber;
13
+ export declare function estimateContractCallGasWithMargin(provider: Provider, from: string, to: string, data: string, marginBps: number, ceiling: bigint): Promise<bigint | null>;
14
+ export declare function resolveEip1559FeeFields(provider: Provider): Promise<{
15
+ maxFeePerGas: bigint;
16
+ maxPriorityFeePerGas: bigint;
18
17
  }>;
19
18
  export declare function sendEip1559Transaction(params: {
20
19
  signer: Signer;
21
20
  to: string;
22
21
  data: string;
23
- gasLimit: BigNumber;
24
- }): Promise<ethers5.providers.TransactionResponse>;
22
+ gasLimit: bigint;
23
+ }): Promise<TransactionResponse>;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Build + sign the `DhServerLogin` EIP-712 envelope the lit-ops-server's
3
+ * `POST /api/auth/login` route expects. Used by both the CLI helper and
4
+ * frontends that consume the SDK directly.
5
+ */
6
+ import { Signer, TypedDataField } from "ethers";
7
+ export interface DhServerLoginMessage {
8
+ address: string;
9
+ issuedAt: number;
10
+ nonce: string;
11
+ }
12
+ export interface DhServerLoginPayload {
13
+ chainId: number;
14
+ message: DhServerLoginMessage;
15
+ signature: string;
16
+ }
17
+ export declare function buildLoginDomain(chainId: number): {
18
+ name: string;
19
+ version: string;
20
+ chainId: number;
21
+ };
22
+ export declare const LOGIN_TYPES: Record<string, TypedDataField[]>;
23
+ /**
24
+ * Sign a fresh login envelope. Caller POSTs the returned `payload` to the
25
+ * server's `/api/auth/login` route.
26
+ */
27
+ export declare function buildSignedLoginPayload(signer: Signer, chainId: number): Promise<DhServerLoginPayload>;
@@ -4,7 +4,7 @@
4
4
  * Generates authorization signatures for extend position requests
5
5
  * that can be verified by the extend-position-validator LIT Action.
6
6
  */
7
- import { ethers as ethers5 } from "ethers";
7
+ import { type Wallet } from "ethers";
8
8
  /**
9
9
  * Extend Owner Authorization Interface (matches lit-actions)
10
10
  */
@@ -55,7 +55,7 @@ export declare function buildExtendAuthorizationHash(positionId: string, newTerm
55
55
  * @param signerOrPrecomputed - Either an ethers Wallet (EOA) or { timestamp, signature } for smart contract wallets
56
56
  * @returns Authorization object with signature
57
57
  */
58
- export declare function generateExtendAuthorization(positionId: string, newTerm: number, chainId: number, signerOrPrecomputed: ethers5.Wallet | {
58
+ export declare function generateExtendAuthorization(positionId: string, newTerm: number, chainId: number, signerOrPrecomputed: Wallet | {
59
59
  timestamp: number;
60
60
  signature: string;
61
61
  }): Promise<ExtendOwnerAuthorization>;
@@ -5,7 +5,7 @@
5
5
  * that can be verified by the ucd-mint-validator LIT Action.
6
6
  * Also includes withdrawal authorization utilities.
7
7
  */
8
- import { ethers as ethers5 } from "ethers";
8
+ import { type Provider, type Signer } from "ethers";
9
9
  /**
10
10
  * Owner Authorization Interface (matches lit-actions)
11
11
  */
@@ -58,7 +58,7 @@ export declare function buildMintAuthorizationHash(positionId: string, amount: b
58
58
  * @param signerOrPrecomputed - Either an ethers Signer (EOA) or { timestamp, signature } for smart contract wallets
59
59
  * @returns Authorization object with signature
60
60
  */
61
- export declare function generateMintAuthorization(positionId: string, amount: bigint, chainId: number, signerOrPrecomputed: ethers5.Signer | {
61
+ export declare function generateMintAuthorization(positionId: string, amount: bigint, chainId: number, signerOrPrecomputed: Signer | {
62
62
  timestamp: number;
63
63
  signature: string;
64
64
  }): Promise<MintOwnerAuthorization>;
@@ -113,7 +113,7 @@ export interface BalanceConfirmationAuthorization {
113
113
  * - Signer address is recovered from signature by LIT Action
114
114
  * - LIT Action validates recovered address === position owner
115
115
  */
116
- export declare function generatePaymentAuthorization(positionId: string, amount: bigint, chainId: number, signer: ethers5.Signer): Promise<PaymentOwnerAuthorization>;
116
+ export declare function generatePaymentAuthorization(positionId: string, amount: bigint, chainId: number, signer: Signer): Promise<PaymentOwnerAuthorization>;
117
117
  /**
118
118
  * Generate extend position authorization signature
119
119
  *
@@ -131,7 +131,7 @@ export declare function generatePaymentAuthorization(positionId: string, amount:
131
131
  * - Signer address is recovered from signature by LIT Action
132
132
  * - LIT Action validates recovered address === position owner
133
133
  */
134
- export declare function generateExtendAuthorization(positionId: string, selectedTerm: number, chainId: number, signer: ethers5.Signer): Promise<ExtendOwnerAuthorization>;
134
+ export declare function generateExtendAuthorization(positionId: string, selectedTerm: number, chainId: number, signer: Signer): Promise<ExtendOwnerAuthorization>;
135
135
  /**
136
136
  * Optional Chipotle service fallback for `getPKPPublicKeyFromTokenId`.
137
137
  *
@@ -143,7 +143,8 @@ export declare function generateExtendAuthorization(positionId: string, selected
143
143
  */
144
144
  export interface ChipotleServiceFallback {
145
145
  serviceEndpoint: string;
146
- serviceAuthToken?: string;
146
+ /** Returns `Authorization`-style headers for the lit-ops-server request. */
147
+ getAuthHeader?: () => Promise<Record<string, string>>;
147
148
  borrowerAddress?: string;
148
149
  timeoutMs?: number;
149
150
  debug?: boolean;
@@ -165,7 +166,7 @@ export interface ChipotleServiceFallback {
165
166
  * @param chipotleFallback - Service-mode fallback used when pkpTokenId is a Chipotle id
166
167
  * @returns PKP public key as hex string with '0x' prefix
167
168
  */
168
- export declare function getPKPPublicKeyFromTokenId(pkpTokenId: string, provider?: ethers5.providers.Provider, pkpNftContractAddress?: string, chipotleFallback?: ChipotleServiceFallback): Promise<string>;
169
+ export declare function getPKPPublicKeyFromTokenId(pkpTokenId: string, provider?: Provider, pkpNftContractAddress?: string, chipotleFallback?: ChipotleServiceFallback): Promise<string>;
169
170
  /**
170
171
  * Withdraw Owner Authorization Interface (matches lit-actions)
171
172
  */
@@ -218,7 +219,7 @@ export declare function buildWithdrawAuthorizationHash(positionId: string, amoun
218
219
  * @returns Authorization object with signature
219
220
  */
220
221
  export declare function generateWithdrawAuthorization(positionId: string, amount: bigint, // satoshis
221
- chainId: number, signerOrPrecomputed: ethers5.Signer | {
222
+ chainId: number, signerOrPrecomputed: Signer | {
222
223
  timestamp: number;
223
224
  signature: string;
224
225
  }, destinationAddress: string): Promise<WithdrawOwnerAuthorization>;
@@ -244,4 +245,4 @@ chainId: number, signerOrPrecomputed: ethers5.Signer | {
244
245
  * @param signer - Ethereum signer to sign with (the caller)
245
246
  * @returns Authorization object with signature
246
247
  */
247
- export declare function generateBalanceConfirmationAuthorization(positionId: string, chainId: number, signer: ethers5.Signer): Promise<BalanceConfirmationAuthorization>;
248
+ export declare function generateBalanceConfirmationAuthorization(positionId: string, chainId: number, signer: Signer): Promise<BalanceConfirmationAuthorization>;
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Position Delegate Utilities
3
+ *
4
+ * Helpers for registering an off-chain authorization delegate on a position.
5
+ * The delegate lets a Safe-as-borrower delegate LIT Action auth signing to a
6
+ * hot agent EOA without making that EOA a Safe owner. The delegate is read by
7
+ * the LIT Action authorization verifier as a third recovery arm after the
8
+ * EOA `position.borrower` check and the EIP-1271 smart-account fallback.
9
+ *
10
+ * State lives on `PositionDelegateRegistry` (a standalone contract), not on
11
+ * PositionManager — PositionManager is at the 24 KiB Spurious Dragon limit
12
+ * and cannot carry the additional storage + setter without going over.
13
+ */
14
+ import { type Signer, type Provider, type TransactionResponse } from "ethers";
15
+ /**
16
+ * Register (or revoke) the off-chain authorization delegate for a position.
17
+ *
18
+ * Must be called by the position's current `borrower` — for Safe-as-borrower
19
+ * setups, that means the call must go through `safe.execTransaction(...)` or
20
+ * `agentModule.execute(...)` so that `msg.sender` at the registry equals the
21
+ * Safe. Pass `ethers.constants.AddressZero` as `delegate` to revoke.
22
+ *
23
+ * @param positionId Position identifier (bytes32).
24
+ * @param delegate New delegate EOA, or zero address to clear.
25
+ * @param signer Ethers signer that will be `msg.sender` at the registry.
26
+ * @param registryAddress Deployed `PositionDelegateRegistry` address for the chain.
27
+ * @returns The submitted transaction response.
28
+ */
29
+ export declare function setPositionDelegate(positionId: string, delegate: string, signer: Signer, registryAddress: string): Promise<TransactionResponse>;
30
+ /**
31
+ * Read the currently registered delegate for a position.
32
+ *
33
+ * Returns the zero address when no delegate has been registered. Pure view;
34
+ * any provider works (signer not required).
35
+ *
36
+ * @param positionId Position identifier (bytes32).
37
+ * @param provider Ethers provider or signer.
38
+ * @param registryAddress Deployed `PositionDelegateRegistry` address.
39
+ * @returns The delegate EOA, or zero address if none.
40
+ */
41
+ export declare function getPositionDelegate(positionId: string, provider: Provider | Signer, registryAddress: string): Promise<string>;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * In-memory session JWT manager for lit-ops-server.
3
+ *
4
+ * The server's `POST /api/auth/login` route accepts an EIP-712-signed
5
+ * `DhServerLogin` envelope and returns an HS256 JWT with a 15-minute TTL.
6
+ * This helper:
7
+ *
8
+ * - caches the JWT until ~30s before expiry,
9
+ * - coalesces concurrent callers behind a single in-flight Promise so we
10
+ * don't spam `/api/auth/login` on parallel SDK calls,
11
+ * - exposes `getValidToken()` returning the live token and
12
+ * `getAuthHeader()` returning a ready-to-spread `{ Authorization: ... }`
13
+ * object.
14
+ *
15
+ * Browser-safe — no filesystem touches. The CLI mirrors this shape but
16
+ * persists to `~/.diamond-hands/session.json` for cross-invocation reuse.
17
+ */
18
+ import type { Signer } from "ethers";
19
+ export interface ServerSessionOptions {
20
+ signer: Signer;
21
+ serviceEndpoint: string;
22
+ chainId: number;
23
+ /** Override for tests. */
24
+ now?: () => number;
25
+ /** Override for tests. */
26
+ fetchImpl?: typeof fetch;
27
+ }
28
+ export declare class ServerSession {
29
+ private readonly signer;
30
+ private readonly serviceEndpoint;
31
+ private readonly chainId;
32
+ private readonly now;
33
+ private readonly fetchImpl;
34
+ private cached;
35
+ private inFlight;
36
+ constructor(opts: ServerSessionOptions);
37
+ /** Returns a JWT good for at least `REFRESH_LEEWAY_SECONDS` more seconds. */
38
+ getValidToken(): Promise<string>;
39
+ /** Convenience for fetch: spread directly into `headers`. */
40
+ getAuthHeader(): Promise<Record<string, string>>;
41
+ /** Drop the cached token (e.g. on 401 from server). Next call re-logs in. */
42
+ clear(): void;
43
+ private getOrRefresh;
44
+ }
@@ -1,10 +1,13 @@
1
1
  /**
2
2
  * Signature Tempering Utility
3
3
  *
4
- * Security testing tool to intentionally corrupt signatures
5
- * to prove that smart contracts properly validate and reject invalid signatures.
4
+ * Security testing tool to intentionally corrupt signatures so tests can prove
5
+ * the on-chain validator rejects invalid signatures.
6
6
  *
7
- * WARNING: This is for TESTING ONLY. Tempered signatures will cause transactions to FAIL.
7
+ * WARNING: TESTING ONLY. `maybeTemperSignature` refuses to corrupt signatures
8
+ * when `NODE_ENV === "production"`, regardless of the config flag. The previous
9
+ * behavior (any caller could flip `temperSignaturesTest: true` to corrupt every
10
+ * signature) was an audit finding — the function is now defense-in-depth.
8
11
  */
9
12
  /**
10
13
  * Tempers a signature by modifying the 3rd character with a random valid hex character