@elisym/sdk 0.3.3 → 0.4.0

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.
package/dist/index.d.cts CHANGED
@@ -1,34 +1,53 @@
1
+ import { Address, TransactionSigner, Rpc, SolanaRpcApi } from '@solana/kit';
1
2
  import { P as PaymentRequestData, a as PaymentValidationError, V as VerifyOptions, b as VerifyResult, S as SubCloser, N as Network, A as Agent, E as ElisymIdentity, C as CapabilityCard, c as SubmitJobOptions, J as JobSubscriptionOptions, d as Job, e as PingResult, f as ElisymClientConfig, g as AgentConfig } from './types-CII4k_8d.cjs';
2
3
  export { h as Capability, I as Identity, i as JobStatus, j as JobUpdateCallbacks, L as LlmConfig, k as NetworkStats, l as PaymentAddress, m as PaymentInfo, n as PaymentValidationCode, W as WalletConfig } from './types-CII4k_8d.cjs';
3
4
  import { Filter, Event } from 'nostr-tools';
4
- import { Transaction } from '@solana/web3.js';
5
5
 
6
+ /**
7
+ * Protocol fee + treasury inputs for building a payment request.
8
+ *
9
+ * In Phase 2 the SDK no longer reads PROTOCOL_FEE_BPS / PROTOCOL_TREASURY
10
+ * from constants. Callers supply this config so they can either pass
11
+ * the bundled fallbacks or, in Phase 3, values fetched from the on-chain
12
+ * elisym-config program.
13
+ */
14
+ interface ProtocolConfigInput {
15
+ /** Protocol fee in basis points (300 = 3%). Must be a non-negative integer. */
16
+ feeBps: number;
17
+ /** Solana address of the protocol treasury. */
18
+ treasury: Address;
19
+ }
6
20
  /**
7
21
  * Pluggable payment strategy interface.
8
22
  * Implement this for each payment chain (Solana, Lightning, Cashu, EVM).
23
+ *
24
+ * The interface is intentionally generic about the on-chain transaction type
25
+ * (`unknown` for build/verify inputs) so future chains can plug in without
26
+ * pulling Solana types into shared code paths.
9
27
  */
10
28
  interface PaymentStrategy {
11
29
  readonly chain: string;
12
30
  /** Calculate protocol fee using basis-point math. */
13
- calculateFee(amount: number): number;
31
+ calculateFee(amount: number, config: ProtocolConfigInput): number;
14
32
  /** Create a payment request with auto-calculated protocol fee. */
15
- createPaymentRequest(recipientAddress: string, amount: number, expirySecs?: number): PaymentRequestData;
33
+ createPaymentRequest(recipientAddress: string, amount: number, config: ProtocolConfigInput, options?: {
34
+ expirySecs?: number;
35
+ }): PaymentRequestData;
16
36
  /**
17
37
  * Validate that a payment request has the correct recipient and protocol fee.
18
38
  * Returns a typed validation error if invalid, null if OK.
19
39
  */
20
- validatePaymentRequest(requestJson: string, expectedRecipient?: string): PaymentValidationError | null;
40
+ validatePaymentRequest(requestJson: string, config: ProtocolConfigInput, expectedRecipient?: string): PaymentValidationError | null;
21
41
  /**
22
- * Build an unsigned transaction from a payment request.
23
- * Returns chain-specific transaction type. The caller is responsible for signing and sending.
24
- * @example For Solana: `const tx = await strategy.buildTransaction(...) as Transaction;`
42
+ * Build and sign a transaction from a payment request using a TransactionSigner.
43
+ * Returns a chain-specific signed transaction value. The caller is responsible
44
+ * for sending it (e.g. via `rpc.sendTransaction(...).send()`).
25
45
  */
26
- buildTransaction(payerAddress: string, paymentRequest: PaymentRequestData): Promise<unknown>;
46
+ buildTransaction(paymentRequest: PaymentRequestData, payerSigner: TransactionSigner, rpc: Rpc<SolanaRpcApi>, config: ProtocolConfigInput): Promise<unknown>;
27
47
  /**
28
48
  * Verify a payment on-chain.
29
- * @param connection Chain-specific connection (e.g. Solana `Connection`).
30
49
  */
31
- verifyPayment(connection: unknown, paymentRequest: PaymentRequestData, options?: VerifyOptions): Promise<VerifyResult>;
50
+ verifyPayment(rpc: Rpc<SolanaRpcApi>, paymentRequest: PaymentRequestData, config: ProtocolConfigInput, options?: VerifyOptions): Promise<VerifyResult>;
32
51
  }
33
52
 
34
53
  declare class NostrPool {
@@ -265,33 +284,98 @@ declare class ElisymClient {
265
284
 
266
285
  declare class SolanaPaymentStrategy implements PaymentStrategy {
267
286
  readonly chain = "solana";
268
- calculateFee(amount: number): number;
269
- createPaymentRequest(recipientAddress: string, amount: number, expirySecs?: number): PaymentRequestData;
270
- validatePaymentRequest(requestJson: string, expectedRecipient?: string): PaymentValidationError | null;
287
+ calculateFee(amount: number, config: ProtocolConfigInput): number;
288
+ createPaymentRequest(recipientAddress: string, amount: number, config: ProtocolConfigInput, options?: {
289
+ expirySecs?: number;
290
+ }): PaymentRequestData;
291
+ validatePaymentRequest(requestJson: string, config: ProtocolConfigInput, expectedRecipient?: string): PaymentValidationError | null;
271
292
  /**
272
- * Build an unsigned transaction from a payment request.
273
- * The caller must set `recentBlockhash` and `feePayer` on the
274
- * returned Transaction before signing and sending.
293
+ * Build, sign, and return a transaction for the supplied payment request.
294
+ * The caller is responsible for sending it (e.g. via `rpc.sendTransaction`).
295
+ *
296
+ * The provider transfer instruction includes the payment reference as a
297
+ * read-only, non-signer account so providers can detect the payment via
298
+ * `getSignaturesForAddress(reference)`.
275
299
  */
276
- buildTransaction(payerAddress: string, paymentRequest: PaymentRequestData): Promise<Transaction>;
277
- verifyPayment(connection: unknown, paymentRequest: PaymentRequestData, options?: VerifyOptions): Promise<VerifyResult>;
300
+ buildTransaction(paymentRequest: PaymentRequestData, payerSigner: TransactionSigner, rpc: Rpc<SolanaRpcApi>, config: ProtocolConfigInput): Promise<Readonly<unknown>>;
301
+ verifyPayment(rpc: Rpc<SolanaRpcApi>, paymentRequest: PaymentRequestData, config: ProtocolConfigInput, options?: VerifyOptions): Promise<VerifyResult>;
278
302
  private _verifyBySignature;
279
303
  private _verifyByReference;
280
304
  }
305
+ /**
306
+ * Build the System program transfer instructions for a payment request.
307
+ *
308
+ * Returns the provider-amount transfer (with the payment reference attached
309
+ * as a read-only, non-signer account) and, if present, the protocol-fee
310
+ * transfer. Exposed so callers and tests can inspect amounts before signing.
311
+ *
312
+ * Caller is responsible for validating `paymentRequest` upstream;
313
+ * `buildTransaction` already does that before invoking this helper.
314
+ */
315
+ declare function buildPaymentInstructions(paymentRequest: PaymentRequestData, payerSigner: TransactionSigner): readonly unknown[];
316
+ /**
317
+ * Convenience wrapper: fetch the on-chain protocol config first, then build a
318
+ * payment request using its current fee/treasury values.
319
+ *
320
+ * Suitable for callers that want to "do the right thing" without managing the
321
+ * config cache or the SolanaPaymentStrategy instance themselves. Uses the same
322
+ * cache as `getProtocolConfig`, so back-to-back calls within the TTL only hit
323
+ * RPC once.
324
+ */
325
+ declare function createPaymentRequestWithOnchainConfig(rpc: Rpc<SolanaRpcApi>, programId: Address, recipient: string, amount: number, options?: {
326
+ expirySecs?: number;
327
+ }): Promise<PaymentRequestData>;
281
328
 
282
329
  /** Assert that a value is a non-negative integer (lamports). */
283
330
  declare function assertLamports(value: number, field: string): void;
284
331
  /**
285
- * Calculate protocol fee using Decimal basis-point math (no floats).
286
- * Returns ceil(amount * PROTOCOL_FEE_BPS / 10000).
287
- * Safe for amounts up to Number.MAX_SAFE_INTEGER - Decimal handles intermediate values.
332
+ * Calculate the protocol fee using basis-point math (no floats).
333
+ * Returns ceil(amount * feeBps / 10000).
334
+ *
335
+ * The caller passes the current fee (in basis points). Phase 2 of the
336
+ * Solana Kit migration removes the implicit dependency on PROTOCOL_FEE_BPS
337
+ * so callers can supply on-chain or test values.
288
338
  */
289
- declare function calculateProtocolFee(amount: number): number;
339
+ declare function calculateProtocolFee(amount: number, feeBps: number): number;
290
340
  /** Validate payment request timestamps. Returns error message or null if valid. */
291
341
  declare function validateExpiry(createdAt: number, expirySecs: number): string | null;
292
342
  /** Assert that payment request timestamps are valid and not expired. Throws on failure. */
293
343
  declare function assertExpiry(createdAt: number, expirySecs: number): void;
294
344
 
345
+ /**
346
+ * Snapshot of the on-chain elisym-config program state.
347
+ *
348
+ * `source` reflects how this snapshot was obtained:
349
+ * - `onchain`: fresh fetch via RPC.
350
+ * - `cache`: served from in-memory cache (still within TTL or stale-while-error).
351
+ *
352
+ * If RPC fails and no cached value exists, `getProtocolConfig` throws instead of
353
+ * returning stale hardcoded defaults - callers must handle the error explicitly.
354
+ */
355
+ interface ProtocolConfig {
356
+ programId: Address;
357
+ feeBps: number;
358
+ treasury: Address;
359
+ admin: Address;
360
+ pendingAdmin: Address | null;
361
+ paused: boolean;
362
+ version: number;
363
+ source: 'onchain' | 'cache';
364
+ }
365
+ declare function clearProtocolConfigCache(): void;
366
+ interface GetProtocolConfigOptions {
367
+ ttlMs?: number;
368
+ forceRefresh?: boolean;
369
+ }
370
+ /**
371
+ * Fetch the protocol config from the on-chain `elisym-config` program.
372
+ *
373
+ * Caches per-program-id with a TTL (default 60s). On RPC error, returns the
374
+ * last known good snapshot from cache. If nothing is cached, throws - callers
375
+ * must handle the error (e.g. refuse the payment, show a warning).
376
+ */
377
+ declare function getProtocolConfig(rpc: Rpc<SolanaRpcApi>, programId: Address, options?: GetProtocolConfigOptions): Promise<ProtocolConfig>;
378
+
295
379
  /** Encrypt plaintext using NIP-44 v2 (sender secret key + recipient public key). */
296
380
  declare function nip44Encrypt(plaintext: string, senderSk: Uint8Array, recipientPubkey: string): string;
297
381
  /** Decrypt ciphertext using NIP-44 v2 (receiver secret key + sender public key). */
@@ -341,10 +425,34 @@ declare function jobResultKind(offset: number): number;
341
425
  declare const KIND_PING = 20200;
342
426
  declare const KIND_PONG = 20201;
343
427
  declare const LAMPORTS_PER_SOL = 1000000000;
344
- /** Protocol fee in basis points (300 = 3%). */
428
+ /**
429
+ * @deprecated Fallback only - use `getProtocolConfig(rpc, programId)` for live values.
430
+ *
431
+ * Protocol fee in basis points (300 = 3%). Bundled as a default for offline use
432
+ * and for first-call before the on-chain config has been fetched. The on-chain
433
+ * `elisym-config` program is the source of truth.
434
+ */
345
435
  declare const PROTOCOL_FEE_BPS = 300;
346
- /** Solana address of the protocol treasury. */
347
- declare const PROTOCOL_TREASURY = "GY7vnWMkKpftU4nQ16C2ATkj1JwrQpHhknkaBUn67VTy";
436
+ /**
437
+ * @deprecated Fallback only - use `getProtocolConfig(rpc, programId)` for live values.
438
+ *
439
+ * Solana address of the protocol treasury. Bundled fallback; the on-chain
440
+ * `elisym-config` program is the source of truth and may rotate this address.
441
+ */
442
+ declare const PROTOCOL_TREASURY: Address;
443
+ /**
444
+ * Solana program ID for the elisym protocol config (devnet deployment).
445
+ *
446
+ * The Anchor program at this address is the source of truth for fee bps,
447
+ * treasury address, and admin rotation state. Read via `getProtocolConfig`.
448
+ */
449
+ declare const PROTOCOL_PROGRAM_ID_DEVNET: Address;
450
+ type ProtocolCluster = 'devnet' | 'mainnet' | 'localnet';
451
+ /**
452
+ * Resolve the elisym-config program ID for a given Solana cluster.
453
+ * Mainnet is intentionally unsupported until the program ships there.
454
+ */
455
+ declare function getProtocolProgramId(cluster: ProtocolCluster): Address;
348
456
  /** Default values for timeouts, retries, and batch sizes. */
349
457
  declare const DEFAULTS: {
350
458
  readonly SUBSCRIPTION_TIMEOUT_MS: 120000;
@@ -374,4 +482,4 @@ declare const LIMITS: {
374
482
  readonly MAX_CAPABILITY_LENGTH: 64;
375
483
  };
376
484
 
377
- export { Agent, AgentConfig, BoundedSet, CapabilityCard, DEFAULTS, DEFAULT_KIND_OFFSET, DiscoveryService, ElisymClient, ElisymClientConfig, type ElisymClientFullConfig, ElisymIdentity, Job, JobSubscriptionOptions, KIND_APP_HANDLER, KIND_JOB_FEEDBACK, KIND_JOB_REQUEST, KIND_JOB_REQUEST_BASE, KIND_JOB_RESULT, KIND_JOB_RESULT_BASE, KIND_PING, KIND_PONG, LAMPORTS_PER_SOL, LIMITS, MarketplaceService, MediaService, Network, NostrPool, PROTOCOL_FEE_BPS, PROTOCOL_TREASURY, PaymentRequestData, type PaymentStrategy, PaymentValidationError, PingResult, PingService, RELAYS, SolanaPaymentStrategy, SubCloser, SubmitJobOptions, VerifyOptions, VerifyResult, assertExpiry, assertLamports, calculateProtocolFee, formatSol, jobRequestKind, jobResultKind, nip44Decrypt, nip44Encrypt, serializeConfig, timeAgo, toDTag, truncateKey, validateAgentName, validateExpiry };
485
+ export { Agent, AgentConfig, BoundedSet, CapabilityCard, DEFAULTS, DEFAULT_KIND_OFFSET, DiscoveryService, ElisymClient, ElisymClientConfig, type ElisymClientFullConfig, ElisymIdentity, type GetProtocolConfigOptions, Job, JobSubscriptionOptions, KIND_APP_HANDLER, KIND_JOB_FEEDBACK, KIND_JOB_REQUEST, KIND_JOB_REQUEST_BASE, KIND_JOB_RESULT, KIND_JOB_RESULT_BASE, KIND_PING, KIND_PONG, LAMPORTS_PER_SOL, LIMITS, MarketplaceService, MediaService, Network, NostrPool, PROTOCOL_FEE_BPS, PROTOCOL_PROGRAM_ID_DEVNET, PROTOCOL_TREASURY, PaymentRequestData, type PaymentStrategy, PaymentValidationError, PingResult, PingService, type ProtocolCluster, type ProtocolConfig, type ProtocolConfigInput, RELAYS, SolanaPaymentStrategy, SubCloser, SubmitJobOptions, VerifyOptions, VerifyResult, assertExpiry, assertLamports, buildPaymentInstructions, calculateProtocolFee, clearProtocolConfigCache, createPaymentRequestWithOnchainConfig, formatSol, getProtocolConfig, getProtocolProgramId, jobRequestKind, jobResultKind, nip44Decrypt, nip44Encrypt, serializeConfig, timeAgo, toDTag, truncateKey, validateAgentName, validateExpiry };
package/dist/index.d.ts CHANGED
@@ -1,34 +1,53 @@
1
+ import { Address, TransactionSigner, Rpc, SolanaRpcApi } from '@solana/kit';
1
2
  import { P as PaymentRequestData, a as PaymentValidationError, V as VerifyOptions, b as VerifyResult, S as SubCloser, N as Network, A as Agent, E as ElisymIdentity, C as CapabilityCard, c as SubmitJobOptions, J as JobSubscriptionOptions, d as Job, e as PingResult, f as ElisymClientConfig, g as AgentConfig } from './types-CII4k_8d.js';
2
3
  export { h as Capability, I as Identity, i as JobStatus, j as JobUpdateCallbacks, L as LlmConfig, k as NetworkStats, l as PaymentAddress, m as PaymentInfo, n as PaymentValidationCode, W as WalletConfig } from './types-CII4k_8d.js';
3
4
  import { Filter, Event } from 'nostr-tools';
4
- import { Transaction } from '@solana/web3.js';
5
5
 
6
+ /**
7
+ * Protocol fee + treasury inputs for building a payment request.
8
+ *
9
+ * In Phase 2 the SDK no longer reads PROTOCOL_FEE_BPS / PROTOCOL_TREASURY
10
+ * from constants. Callers supply this config so they can either pass
11
+ * the bundled fallbacks or, in Phase 3, values fetched from the on-chain
12
+ * elisym-config program.
13
+ */
14
+ interface ProtocolConfigInput {
15
+ /** Protocol fee in basis points (300 = 3%). Must be a non-negative integer. */
16
+ feeBps: number;
17
+ /** Solana address of the protocol treasury. */
18
+ treasury: Address;
19
+ }
6
20
  /**
7
21
  * Pluggable payment strategy interface.
8
22
  * Implement this for each payment chain (Solana, Lightning, Cashu, EVM).
23
+ *
24
+ * The interface is intentionally generic about the on-chain transaction type
25
+ * (`unknown` for build/verify inputs) so future chains can plug in without
26
+ * pulling Solana types into shared code paths.
9
27
  */
10
28
  interface PaymentStrategy {
11
29
  readonly chain: string;
12
30
  /** Calculate protocol fee using basis-point math. */
13
- calculateFee(amount: number): number;
31
+ calculateFee(amount: number, config: ProtocolConfigInput): number;
14
32
  /** Create a payment request with auto-calculated protocol fee. */
15
- createPaymentRequest(recipientAddress: string, amount: number, expirySecs?: number): PaymentRequestData;
33
+ createPaymentRequest(recipientAddress: string, amount: number, config: ProtocolConfigInput, options?: {
34
+ expirySecs?: number;
35
+ }): PaymentRequestData;
16
36
  /**
17
37
  * Validate that a payment request has the correct recipient and protocol fee.
18
38
  * Returns a typed validation error if invalid, null if OK.
19
39
  */
20
- validatePaymentRequest(requestJson: string, expectedRecipient?: string): PaymentValidationError | null;
40
+ validatePaymentRequest(requestJson: string, config: ProtocolConfigInput, expectedRecipient?: string): PaymentValidationError | null;
21
41
  /**
22
- * Build an unsigned transaction from a payment request.
23
- * Returns chain-specific transaction type. The caller is responsible for signing and sending.
24
- * @example For Solana: `const tx = await strategy.buildTransaction(...) as Transaction;`
42
+ * Build and sign a transaction from a payment request using a TransactionSigner.
43
+ * Returns a chain-specific signed transaction value. The caller is responsible
44
+ * for sending it (e.g. via `rpc.sendTransaction(...).send()`).
25
45
  */
26
- buildTransaction(payerAddress: string, paymentRequest: PaymentRequestData): Promise<unknown>;
46
+ buildTransaction(paymentRequest: PaymentRequestData, payerSigner: TransactionSigner, rpc: Rpc<SolanaRpcApi>, config: ProtocolConfigInput): Promise<unknown>;
27
47
  /**
28
48
  * Verify a payment on-chain.
29
- * @param connection Chain-specific connection (e.g. Solana `Connection`).
30
49
  */
31
- verifyPayment(connection: unknown, paymentRequest: PaymentRequestData, options?: VerifyOptions): Promise<VerifyResult>;
50
+ verifyPayment(rpc: Rpc<SolanaRpcApi>, paymentRequest: PaymentRequestData, config: ProtocolConfigInput, options?: VerifyOptions): Promise<VerifyResult>;
32
51
  }
33
52
 
34
53
  declare class NostrPool {
@@ -265,33 +284,98 @@ declare class ElisymClient {
265
284
 
266
285
  declare class SolanaPaymentStrategy implements PaymentStrategy {
267
286
  readonly chain = "solana";
268
- calculateFee(amount: number): number;
269
- createPaymentRequest(recipientAddress: string, amount: number, expirySecs?: number): PaymentRequestData;
270
- validatePaymentRequest(requestJson: string, expectedRecipient?: string): PaymentValidationError | null;
287
+ calculateFee(amount: number, config: ProtocolConfigInput): number;
288
+ createPaymentRequest(recipientAddress: string, amount: number, config: ProtocolConfigInput, options?: {
289
+ expirySecs?: number;
290
+ }): PaymentRequestData;
291
+ validatePaymentRequest(requestJson: string, config: ProtocolConfigInput, expectedRecipient?: string): PaymentValidationError | null;
271
292
  /**
272
- * Build an unsigned transaction from a payment request.
273
- * The caller must set `recentBlockhash` and `feePayer` on the
274
- * returned Transaction before signing and sending.
293
+ * Build, sign, and return a transaction for the supplied payment request.
294
+ * The caller is responsible for sending it (e.g. via `rpc.sendTransaction`).
295
+ *
296
+ * The provider transfer instruction includes the payment reference as a
297
+ * read-only, non-signer account so providers can detect the payment via
298
+ * `getSignaturesForAddress(reference)`.
275
299
  */
276
- buildTransaction(payerAddress: string, paymentRequest: PaymentRequestData): Promise<Transaction>;
277
- verifyPayment(connection: unknown, paymentRequest: PaymentRequestData, options?: VerifyOptions): Promise<VerifyResult>;
300
+ buildTransaction(paymentRequest: PaymentRequestData, payerSigner: TransactionSigner, rpc: Rpc<SolanaRpcApi>, config: ProtocolConfigInput): Promise<Readonly<unknown>>;
301
+ verifyPayment(rpc: Rpc<SolanaRpcApi>, paymentRequest: PaymentRequestData, config: ProtocolConfigInput, options?: VerifyOptions): Promise<VerifyResult>;
278
302
  private _verifyBySignature;
279
303
  private _verifyByReference;
280
304
  }
305
+ /**
306
+ * Build the System program transfer instructions for a payment request.
307
+ *
308
+ * Returns the provider-amount transfer (with the payment reference attached
309
+ * as a read-only, non-signer account) and, if present, the protocol-fee
310
+ * transfer. Exposed so callers and tests can inspect amounts before signing.
311
+ *
312
+ * Caller is responsible for validating `paymentRequest` upstream;
313
+ * `buildTransaction` already does that before invoking this helper.
314
+ */
315
+ declare function buildPaymentInstructions(paymentRequest: PaymentRequestData, payerSigner: TransactionSigner): readonly unknown[];
316
+ /**
317
+ * Convenience wrapper: fetch the on-chain protocol config first, then build a
318
+ * payment request using its current fee/treasury values.
319
+ *
320
+ * Suitable for callers that want to "do the right thing" without managing the
321
+ * config cache or the SolanaPaymentStrategy instance themselves. Uses the same
322
+ * cache as `getProtocolConfig`, so back-to-back calls within the TTL only hit
323
+ * RPC once.
324
+ */
325
+ declare function createPaymentRequestWithOnchainConfig(rpc: Rpc<SolanaRpcApi>, programId: Address, recipient: string, amount: number, options?: {
326
+ expirySecs?: number;
327
+ }): Promise<PaymentRequestData>;
281
328
 
282
329
  /** Assert that a value is a non-negative integer (lamports). */
283
330
  declare function assertLamports(value: number, field: string): void;
284
331
  /**
285
- * Calculate protocol fee using Decimal basis-point math (no floats).
286
- * Returns ceil(amount * PROTOCOL_FEE_BPS / 10000).
287
- * Safe for amounts up to Number.MAX_SAFE_INTEGER - Decimal handles intermediate values.
332
+ * Calculate the protocol fee using basis-point math (no floats).
333
+ * Returns ceil(amount * feeBps / 10000).
334
+ *
335
+ * The caller passes the current fee (in basis points). Phase 2 of the
336
+ * Solana Kit migration removes the implicit dependency on PROTOCOL_FEE_BPS
337
+ * so callers can supply on-chain or test values.
288
338
  */
289
- declare function calculateProtocolFee(amount: number): number;
339
+ declare function calculateProtocolFee(amount: number, feeBps: number): number;
290
340
  /** Validate payment request timestamps. Returns error message or null if valid. */
291
341
  declare function validateExpiry(createdAt: number, expirySecs: number): string | null;
292
342
  /** Assert that payment request timestamps are valid and not expired. Throws on failure. */
293
343
  declare function assertExpiry(createdAt: number, expirySecs: number): void;
294
344
 
345
+ /**
346
+ * Snapshot of the on-chain elisym-config program state.
347
+ *
348
+ * `source` reflects how this snapshot was obtained:
349
+ * - `onchain`: fresh fetch via RPC.
350
+ * - `cache`: served from in-memory cache (still within TTL or stale-while-error).
351
+ *
352
+ * If RPC fails and no cached value exists, `getProtocolConfig` throws instead of
353
+ * returning stale hardcoded defaults - callers must handle the error explicitly.
354
+ */
355
+ interface ProtocolConfig {
356
+ programId: Address;
357
+ feeBps: number;
358
+ treasury: Address;
359
+ admin: Address;
360
+ pendingAdmin: Address | null;
361
+ paused: boolean;
362
+ version: number;
363
+ source: 'onchain' | 'cache';
364
+ }
365
+ declare function clearProtocolConfigCache(): void;
366
+ interface GetProtocolConfigOptions {
367
+ ttlMs?: number;
368
+ forceRefresh?: boolean;
369
+ }
370
+ /**
371
+ * Fetch the protocol config from the on-chain `elisym-config` program.
372
+ *
373
+ * Caches per-program-id with a TTL (default 60s). On RPC error, returns the
374
+ * last known good snapshot from cache. If nothing is cached, throws - callers
375
+ * must handle the error (e.g. refuse the payment, show a warning).
376
+ */
377
+ declare function getProtocolConfig(rpc: Rpc<SolanaRpcApi>, programId: Address, options?: GetProtocolConfigOptions): Promise<ProtocolConfig>;
378
+
295
379
  /** Encrypt plaintext using NIP-44 v2 (sender secret key + recipient public key). */
296
380
  declare function nip44Encrypt(plaintext: string, senderSk: Uint8Array, recipientPubkey: string): string;
297
381
  /** Decrypt ciphertext using NIP-44 v2 (receiver secret key + sender public key). */
@@ -341,10 +425,34 @@ declare function jobResultKind(offset: number): number;
341
425
  declare const KIND_PING = 20200;
342
426
  declare const KIND_PONG = 20201;
343
427
  declare const LAMPORTS_PER_SOL = 1000000000;
344
- /** Protocol fee in basis points (300 = 3%). */
428
+ /**
429
+ * @deprecated Fallback only - use `getProtocolConfig(rpc, programId)` for live values.
430
+ *
431
+ * Protocol fee in basis points (300 = 3%). Bundled as a default for offline use
432
+ * and for first-call before the on-chain config has been fetched. The on-chain
433
+ * `elisym-config` program is the source of truth.
434
+ */
345
435
  declare const PROTOCOL_FEE_BPS = 300;
346
- /** Solana address of the protocol treasury. */
347
- declare const PROTOCOL_TREASURY = "GY7vnWMkKpftU4nQ16C2ATkj1JwrQpHhknkaBUn67VTy";
436
+ /**
437
+ * @deprecated Fallback only - use `getProtocolConfig(rpc, programId)` for live values.
438
+ *
439
+ * Solana address of the protocol treasury. Bundled fallback; the on-chain
440
+ * `elisym-config` program is the source of truth and may rotate this address.
441
+ */
442
+ declare const PROTOCOL_TREASURY: Address;
443
+ /**
444
+ * Solana program ID for the elisym protocol config (devnet deployment).
445
+ *
446
+ * The Anchor program at this address is the source of truth for fee bps,
447
+ * treasury address, and admin rotation state. Read via `getProtocolConfig`.
448
+ */
449
+ declare const PROTOCOL_PROGRAM_ID_DEVNET: Address;
450
+ type ProtocolCluster = 'devnet' | 'mainnet' | 'localnet';
451
+ /**
452
+ * Resolve the elisym-config program ID for a given Solana cluster.
453
+ * Mainnet is intentionally unsupported until the program ships there.
454
+ */
455
+ declare function getProtocolProgramId(cluster: ProtocolCluster): Address;
348
456
  /** Default values for timeouts, retries, and batch sizes. */
349
457
  declare const DEFAULTS: {
350
458
  readonly SUBSCRIPTION_TIMEOUT_MS: 120000;
@@ -374,4 +482,4 @@ declare const LIMITS: {
374
482
  readonly MAX_CAPABILITY_LENGTH: 64;
375
483
  };
376
484
 
377
- export { Agent, AgentConfig, BoundedSet, CapabilityCard, DEFAULTS, DEFAULT_KIND_OFFSET, DiscoveryService, ElisymClient, ElisymClientConfig, type ElisymClientFullConfig, ElisymIdentity, Job, JobSubscriptionOptions, KIND_APP_HANDLER, KIND_JOB_FEEDBACK, KIND_JOB_REQUEST, KIND_JOB_REQUEST_BASE, KIND_JOB_RESULT, KIND_JOB_RESULT_BASE, KIND_PING, KIND_PONG, LAMPORTS_PER_SOL, LIMITS, MarketplaceService, MediaService, Network, NostrPool, PROTOCOL_FEE_BPS, PROTOCOL_TREASURY, PaymentRequestData, type PaymentStrategy, PaymentValidationError, PingResult, PingService, RELAYS, SolanaPaymentStrategy, SubCloser, SubmitJobOptions, VerifyOptions, VerifyResult, assertExpiry, assertLamports, calculateProtocolFee, formatSol, jobRequestKind, jobResultKind, nip44Decrypt, nip44Encrypt, serializeConfig, timeAgo, toDTag, truncateKey, validateAgentName, validateExpiry };
485
+ export { Agent, AgentConfig, BoundedSet, CapabilityCard, DEFAULTS, DEFAULT_KIND_OFFSET, DiscoveryService, ElisymClient, ElisymClientConfig, type ElisymClientFullConfig, ElisymIdentity, type GetProtocolConfigOptions, Job, JobSubscriptionOptions, KIND_APP_HANDLER, KIND_JOB_FEEDBACK, KIND_JOB_REQUEST, KIND_JOB_REQUEST_BASE, KIND_JOB_RESULT, KIND_JOB_RESULT_BASE, KIND_PING, KIND_PONG, LAMPORTS_PER_SOL, LIMITS, MarketplaceService, MediaService, Network, NostrPool, PROTOCOL_FEE_BPS, PROTOCOL_PROGRAM_ID_DEVNET, PROTOCOL_TREASURY, PaymentRequestData, type PaymentStrategy, PaymentValidationError, PingResult, PingService, type ProtocolCluster, type ProtocolConfig, type ProtocolConfigInput, RELAYS, SolanaPaymentStrategy, SubCloser, SubmitJobOptions, VerifyOptions, VerifyResult, assertExpiry, assertLamports, buildPaymentInstructions, calculateProtocolFee, clearProtocolConfigCache, createPaymentRequestWithOnchainConfig, formatSol, getProtocolConfig, getProtocolProgramId, jobRequestKind, jobResultKind, nip44Decrypt, nip44Encrypt, serializeConfig, timeAgo, toDTag, truncateKey, validateAgentName, validateExpiry };