@@ -97,6 +97,70 @@ console.log(`Deposit successful: ${result.hash}`);
9797
9898</Steps >
9999
100+ ## Payment Delegation
101+
102+ The Payment Manager lets one account sponsor the execution costs of another. See the following full lifecycle: Alice funds her ledger, delegates limits to Bob, Bob spends from Alice's balance, and Alice later revokes access. The snippets below mirror that scenario so you can recreate it locally.
103+
104+ - ` Alice ` is the sponsor. She configures spending limits and delegates them to Bob.
105+ - ` Bob ` is the delegate. He signs with his PKP and provides ` userMaxPrice ` that fits within Alice's limits.
106+ - When Bob spends funds, Alice's ledger balance decreases.
107+ - Alice can immediately revoke Bob's access; further requests then fail.
108+
109+ ``` typescript
110+ import { createLitClient } from ' @lit-protocol/lit-client' ;
111+ import { nagaTest } from ' @lit-protocol/networks' ;
112+
113+ // Assume you've already funded Alice's ledger using depositForUser
114+ const litClient = await createLitClient ({ network: nagaTest });
115+ const alicePaymentManager = await litClient .getPaymentManager ({
116+ account: aliceViemAccount ,
117+ });
118+
119+ // 1. Configure Alice's spending restrictions for all delegates
120+ await alicePaymentManager .setRestriction ({
121+ totalMaxPrice: ' 1000000000000000000' , // 1 ETH (wei string)
122+ requestsPerPeriod: ' 100' ,
123+ periodSeconds: ' 5' ,
124+ });
125+
126+ // 2. Delegate access to Bob's EOA address
127+ await alicePaymentManager .delegatePaymentsBatch ({
128+ userAddresses: [bobAddress ],
129+ });
130+
131+ // 3. Optionally inspect Alice's ledger balance before Bob spends
132+ const before = await alicePaymentManager .getBalance ({
133+ userAddress: aliceViemAccount .address ,
134+ });
135+ console .log (' Alice balance before Bob signs:' , before .raw .availableBalance );
136+ ```
137+
138+ When Bob signs, the execution is charged against Alice's ledger (as long as Bob's ` userMaxPrice ` is within Alice's configured limit).
139+
140+ ``` typescript
141+ await litClient .chain .ethereum .pkpSign ({
142+ authContext: bobAuthContext , // Created with Bob's account
143+ pubKey: bobPkpPublicKey ,
144+ toSign: ' Hello, world!' ,
145+ userMaxPrice: 200000000000000000n , // 0.2 ETH in Wei
146+ });
147+ ```
148+
149+ After Bob signs, Alice's balance drops. She can revoke Bob immediately using ` undelegatePaymentsBatch ` . Subsequent attempts by Bob will fail.
150+
151+ ``` typescript
152+ // 4. Confirm Alice's balance decreased
153+ const after = await alicePaymentManager .getBalance ({
154+ userAddress: aliceViemAccount .address ,
155+ });
156+ console .log (' Alice balance after Bob signs:' , after .raw .availableBalance );
157+
158+ // 5. Revoke Bob's access
159+ await alicePaymentManager .undelegatePaymentsBatch ({
160+ userAddresses: [bobAddress ],
161+ });
162+ ```
163+
100164## Auth Service API Endpoints
101165
102166Leverage the hosted Auth Service to manage delegation without exposing private keys in your application:
@@ -113,7 +177,7 @@ import { nagaTest } from '@lit-protocol/networks';
113177// 1. Create the Lit client for the naga-test environment
114178const litClient = await createLitClient ({ network: nagaTest });
115179
116- const authServiceBaseUrl = ' https://naga-test-auth-service.example.com ' ;
180+ const authServiceBaseUrl = ' https://naga-test-auth-service.getlit.dev ' ;
117181const apiKey = process .env .LIT_API_KEY ! ;
118182
119183// 3. Register a payer wallet (store the secret securely server-side)
@@ -148,5 +212,3 @@ console.log('Delegation submitted with tx hash:', delegateResponse.txHash);
148212- The response includes the derived wallet address and the random ` payerSecretKey ` . The server does not store this secret ; you must persist it securely on the client side .
149213- Later , ` /add-users ` expects both headers (` x-api-key ` and ` payer-secret-key ` ). The service recomputes the same derivation index and wallet on the fly , so the same header pair always maps to the same child wallet .
150214- Calling ` /register-payer ` again with the same API key issues a new random ` payerSecretKey ` , which leads to a different child wallet . Choose whether to rotate secrets or keep the original one depending on your application needs .
151-
152- ! [](https :// www.plantuml.com/plantuml/png/XPAn3jCm48PtFyMfKw8IiKSAQcab1a1K58c1CXpEaLWaJcHVIlFs6DkKcBHYYy-Vl_Floyuo6fxwJh3YZc0_SGjdCbSb2KuuzwGPZjHHWwm6BSJeS2NLYAw-ENJAxMy0BOJFT7ifyz3lGbodv3l5qG3lKMD3nlFn-ndh6RTyr3lSFTN5MYo96Xc_eINOh8F2OT1iKFeUzuKGLGKVgL6MoS28CnceAX5lNhnQ1YpXzE7y2LwQY1SUl-ZiLk2eYXyqvsA1hqw_8Kq6cKARCqb3VD57CkfAy1ExZXY-cw67NbC_Q2LX2quCJfnwdJXSi0ogp_xilguDMNlH2_rRcdt2-0m4aoLZ_viGwxhmv3BSYz2iiDuSAXxwydMLEmwaX8RYBBDSnABR_plY4fmCcToZEbUgMM1Ub0uxGoc7INCk0XNJf509Ibj6pGfvPVyNhUCZnRfzZIpRp4VCHGgxu_TVo1zSlAxuim75WoPy0qEIrCWhPJeBZxPeswUpjvEKP2rix-IET3trtIy0)
0 commit comments