@pafi-dev/issuer 0.3.0-alpha.0 → 0.3.0-beta.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,5 +1,5 @@
1
1
  import { Address, Hex, PublicClient, Chain } from 'viem';
2
- import { PointTokenDomainConfig, MintRequest, EIP712Signature, MintParams, SwapParams, ReceiverConsent, PathKey, PoolKey, SponsorshipScenario, PartialUserOperation } from '@pafi-dev/core';
2
+ import { PointTokenDomainConfig, MintRequest, EIP712Signature, MintParams, SwapParams, MintRequestV2, SignatureStruct, PartialUserOperation, BurnConsent, ReceiverConsent, PathKey, PoolKey, SponsorshipScenario } from '@pafi-dev/core';
3
3
  export { encodeExtData } from '@pafi-dev/core';
4
4
 
5
5
  /**
@@ -565,6 +565,75 @@ declare class RelayService {
565
565
  * can ship (blocker B1). Kept for v0.2.x consumers. Removed in 2.0.
566
566
  */
567
567
  submitMintAndSwap(params: SubmitMintAndSwapParams): Promise<RelayResult>;
568
+ /**
569
+ * Build an unsigned UserOp for Scenario 1 (Mint).
570
+ *
571
+ * Flow:
572
+ * 1. Encode `Relayer.mint(request, userSig, issuerSig)` as the inner call
573
+ * 2. Optionally append a PT fee transfer from user → feeRecipient
574
+ * (fee recovery happens on-chain via BatchExecutor, not via an
575
+ * operator wallet)
576
+ * 3. Wrap all inner calls into `BatchExecutor.execute(calls[])`
577
+ * 4. Return a `PartialUserOperation` ready for:
578
+ * - gas estimation (Bundler)
579
+ * - paymaster sponsorship (PAFI Backend)
580
+ * - user signature (Privy)
581
+ */
582
+ prepareMint(params: PrepareMintParams): PartialUserOperation;
583
+ /**
584
+ * Build an unsigned UserOp for Scenario 2 (Burn/Redeem).
585
+ *
586
+ * Two modes:
587
+ * - `mode: 'burn'` — direct `PointToken.burn(amount)`; `msg.sender`
588
+ * via EIP-7702 delegation is the user, so no signature needed
589
+ * on-chain (the BurnConsent was already verified off-chain by
590
+ * the issuer backend before we got here)
591
+ * - `mode: 'burnWithSig'` — `PointToken.burnWithSig(consent, sig)`;
592
+ * used when the issuer hasn't verified the consent and the
593
+ * contract has to do it on-chain
594
+ */
595
+ prepareBurn(params: PrepareBurnParams): PartialUserOperation;
596
+ }
597
+ interface PrepareMintParams {
598
+ /** User EOA that will send the UserOp (via EIP-7702 delegation). */
599
+ userAddress: Address;
600
+ /** ERC-4337 account nonce (not the MintRequest nonce — different namespace). */
601
+ aaNonce: bigint;
602
+ /** Deployed Relayer v2 contract address (chain-specific). */
603
+ relayerAddress: Address;
604
+ /** BatchExecutor delegation target (chain-specific). */
605
+ batchExecutorAddress: Address;
606
+ /** PointToken being minted — used for optional fee transfer call. */
607
+ pointTokenAddress: Address;
608
+ /** EIP-712-signed MintRequest fields. */
609
+ mintRequest: MintRequestV2;
610
+ /** User's EIP-712 signature over `mintRequest`. */
611
+ userSignature: SignatureStruct;
612
+ /** Issuer's EIP-712 signature over `mintRequest`. */
613
+ issuerSignature: SignatureStruct;
614
+ /** Gas limits — defaults are conservative; caller can tighten. */
615
+ callGasLimit?: bigint;
616
+ verificationGasLimit?: bigint;
617
+ preVerificationGas?: bigint;
618
+ }
619
+ type PrepareBurnParams = PrepareBurnDirectParams | PrepareBurnWithSigParams;
620
+ interface PrepareBurnCommonParams {
621
+ userAddress: Address;
622
+ aaNonce: bigint;
623
+ pointTokenAddress: Address;
624
+ batchExecutorAddress: Address;
625
+ callGasLimit?: bigint;
626
+ verificationGasLimit?: bigint;
627
+ preVerificationGas?: bigint;
628
+ }
629
+ interface PrepareBurnDirectParams extends PrepareBurnCommonParams {
630
+ mode: "burn";
631
+ amount: bigint;
632
+ }
633
+ interface PrepareBurnWithSigParams extends PrepareBurnCommonParams {
634
+ mode: "burnWithSig";
635
+ burnConsent: BurnConsent;
636
+ consentSignature: SignatureStruct;
568
637
  }
569
638
 
570
639
  interface FeeManagerConfig {
@@ -1260,6 +1329,143 @@ declare class IssuerApiHandlers {
1260
1329
  handleClaimAndSwap(userAddress: Address, request: ApiClaimAndSwapRequest): Promise<ApiClaimAndSwapResponse>;
1261
1330
  }
1262
1331
 
1332
+ /**
1333
+ * v1.4 reverse flow — **Variant A**: user-initiated PT redeem.
1334
+ *
1335
+ * User has on-chain PT, wants to convert back to off-chain points. They
1336
+ * sign a `BurnConsent`, the issuer backend verifies it, reserves an
1337
+ * off-chain credit, and returns an unsigned UserOp that the frontend
1338
+ * submits via the Bundler. When the burn lands, the `BurnIndexer`
1339
+ * (elsewhere) resolves the credit.
1340
+ *
1341
+ * **Mocked SC contracts** — this handler compiles + wires end-to-end
1342
+ * against `@pafi-dev/core/contracts` mock ABIs. When SC ships real
1343
+ * ABIs, no changes here — only `contracts/index.ts` re-export flips.
1344
+ */
1345
+ interface PTRedeemHandlerConfig {
1346
+ ledger: IPointLedger;
1347
+ relayService: RelayService;
1348
+ provider: PublicClient;
1349
+ /** PointToken contract address (chain-specific). */
1350
+ pointTokenAddress: Address;
1351
+ /** BatchExecutor delegation target (chain-specific). */
1352
+ batchExecutorAddress: Address;
1353
+ /** Chain id — used for domain separator when verifying BurnConsent. */
1354
+ chainId: number;
1355
+ /**
1356
+ * EIP-712 domain fields. Must match the on-chain PointToken's domain
1357
+ * separator exactly, or signature verification fails. `name` is
1358
+ * typically the PointToken's ERC-20 name (e.g. "PAFI Starbucks
1359
+ * Points"). `verifyingContract` defaults to `pointTokenAddress`.
1360
+ */
1361
+ domain: {
1362
+ name: string;
1363
+ verifyingContract?: Address;
1364
+ };
1365
+ /**
1366
+ * How long the pending credit stays reserved if the burn never lands.
1367
+ * Default: 15 min — long enough for a bundler submission + confirmation.
1368
+ */
1369
+ redeemLockDurationMs?: number;
1370
+ /** Clock injection for tests; defaults to `Date.now`. */
1371
+ now?: () => number;
1372
+ }
1373
+ interface PTRedeemRequest {
1374
+ userAddress: Address;
1375
+ amount: bigint;
1376
+ /** Serialized EIP-712 signature over the BurnConsent. */
1377
+ consentSignature: Hex;
1378
+ consent: BurnConsent;
1379
+ /** ERC-4337 account nonce for the user's EOA. */
1380
+ aaNonce: bigint;
1381
+ }
1382
+ interface PTRedeemResponse {
1383
+ /** Lock id from the ledger — client polls status with this. */
1384
+ lockId: string;
1385
+ /** Unsigned UserOp — FE attaches paymaster + user signature + submits. */
1386
+ userOp: PartialUserOperation;
1387
+ /** Seconds until the lock expires if the burn doesn't land. */
1388
+ expiresInSeconds: number;
1389
+ }
1390
+ declare class PTRedeemError extends Error {
1391
+ code: "INVALID_CONSENT" | "SIGNATURE_MISMATCH" | "AMOUNT_MISMATCH" | "EXPIRED_CONSENT" | "LEDGER_NOT_SUPPORTED";
1392
+ constructor(code: "INVALID_CONSENT" | "SIGNATURE_MISMATCH" | "AMOUNT_MISMATCH" | "EXPIRED_CONSENT" | "LEDGER_NOT_SUPPORTED", message: string);
1393
+ }
1394
+ declare class PTRedeemHandler {
1395
+ private readonly ledger;
1396
+ private readonly relayService;
1397
+ private readonly pointTokenAddress;
1398
+ private readonly batchExecutorAddress;
1399
+ private readonly chainId;
1400
+ private readonly domain;
1401
+ private readonly redeemLockDurationMs;
1402
+ private readonly now;
1403
+ constructor(config: PTRedeemHandlerConfig);
1404
+ handle(request: PTRedeemRequest): Promise<PTRedeemResponse>;
1405
+ }
1406
+
1407
+ /**
1408
+ * v1.4 reverse flow — **Variant B**: auto top-up on voucher redemption.
1409
+ *
1410
+ * User tries to redeem a voucher for `requiredAmount` off-chain points
1411
+ * but their off-chain balance is short. If their on-chain PT balance is
1412
+ * enough to cover the shortfall, this handler auto-triggers a burn for
1413
+ * exactly the shortfall amount so the voucher can proceed.
1414
+ *
1415
+ * Required off-chain: 500
1416
+ * Available off-chain: 300
1417
+ * Shortfall: 200
1418
+ * On-chain PT: 250 ← enough, top-up fires
1419
+ * → burn 200 PT, credit 200 off-chain, voucher proceeds with 500
1420
+ *
1421
+ * Delegates the actual burn construction to {@link PTRedeemHandler}
1422
+ * — this handler is pure business logic (calculating shortfall +
1423
+ * checking on-chain balance) on top.
1424
+ */
1425
+ interface TopUpRedemptionHandlerConfig {
1426
+ ledger: IPointLedger;
1427
+ ptRedeemHandler: PTRedeemHandler;
1428
+ provider: PublicClient;
1429
+ /** PointToken contract address (chain-specific). */
1430
+ pointTokenAddress: Address;
1431
+ }
1432
+ interface TopUpRedemptionRequest {
1433
+ userAddress: Address;
1434
+ /** Total points the voucher redemption requires off-chain. */
1435
+ requiredAmount: bigint;
1436
+ /**
1437
+ * The user's pre-signed `BurnConsent` + signature, prepared by the FE
1438
+ * with amount set to a worst-case upper bound. Handler inspects the
1439
+ * shortfall and uses the consent if the shortfall ≤ consent.amount.
1440
+ */
1441
+ redeemRequest: Pick<PTRedeemRequest, "consent" | "consentSignature" | "aaNonce">;
1442
+ }
1443
+ type TopUpRedemptionResponse = {
1444
+ action: "NO_TOP_UP_NEEDED";
1445
+ offChainBalance: bigint;
1446
+ } | {
1447
+ action: "INSUFFICIENT_ONCHAIN";
1448
+ offChainBalance: bigint;
1449
+ onChainBalance: bigint;
1450
+ shortfall: bigint;
1451
+ } | {
1452
+ action: "TOP_UP_STARTED";
1453
+ shortfall: bigint;
1454
+ redeem: PTRedeemResponse;
1455
+ };
1456
+ declare class TopUpRedemptionError extends Error {
1457
+ code: "INSUFFICIENT_ONCHAIN_BALANCE" | "CONSENT_AMOUNT_TOO_LOW" | "LEDGER_NOT_SUPPORTED";
1458
+ constructor(code: "INSUFFICIENT_ONCHAIN_BALANCE" | "CONSENT_AMOUNT_TOO_LOW" | "LEDGER_NOT_SUPPORTED", message: string);
1459
+ }
1460
+ declare class TopUpRedemptionHandler {
1461
+ private readonly ledger;
1462
+ private readonly ptRedeemHandler;
1463
+ private readonly provider;
1464
+ private readonly pointTokenAddress;
1465
+ constructor(config: TopUpRedemptionHandlerConfig);
1466
+ handle(request: TopUpRedemptionRequest): Promise<TopUpRedemptionResponse>;
1467
+ }
1468
+
1263
1469
  /**
1264
1470
  * Config for `createSubgraphPoolsProvider`.
1265
1471
  */
@@ -1716,4 +1922,4 @@ declare function createIssuerService(config: IssuerServiceConfig): IssuerService
1716
1922
  /** SDK package version — bumped on every release */
1717
1923
  declare const PAFI_ISSUER_SDK_VERSION = "0.1.0";
1718
1924
 
1719
- export { type ApiBuildConsentTypedDataRequest, type ApiBuildConsentTypedDataResponse, type ApiClaimAndSwapRequest, type ApiClaimAndSwapResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig, BalanceAggregator, type BalanceAggregatorConfig, type BurnEvent, BurnIndexer, type BurnIndexerConfig, type CombinedBalance, DefaultPolicyEngine, type DefaultPolicyEngineOptions, FeeManager, type FeeManagerConfig, type IIndexerCursorStore, type IIssuerSigner, type IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerService, type IssuerServiceConfig, type LockedMintRequest, type LoginResult, MemoryPointLedger, MemorySessionStore, type MemorySessionStoreOptions, type MintAndCashOutRequest, type MintAndCashOutResponse, type MintEvent, MintingGateway, type MintingGatewayConfig, MintingGatewayError, type MintingGatewayErrorCode, type MintingStatus, NonceManager, type OperatorWalletLike, PAFI_ISSUER_SDK_VERSION, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, PrivateKeySigner, type PrivateKeySignerOptions, RelayError, type RelayErrorCode, type RelayResult, RelayService, type RelayServiceConfig, type Session, type SponsorshipRequest, type SponsorshipResponse, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, type SubmitMintAndSwapParams, authenticateRequest, createIssuerService, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider };
1925
+ export { type ApiBuildConsentTypedDataRequest, type ApiBuildConsentTypedDataResponse, type ApiClaimAndSwapRequest, type ApiClaimAndSwapResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig, BalanceAggregator, type BalanceAggregatorConfig, type BurnEvent, BurnIndexer, type BurnIndexerConfig, type CombinedBalance, DefaultPolicyEngine, type DefaultPolicyEngineOptions, FeeManager, type FeeManagerConfig, type IIndexerCursorStore, type IIssuerSigner, type IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerService, type IssuerServiceConfig, type LockedMintRequest, type LoginResult, MemoryPointLedger, MemorySessionStore, type MemorySessionStoreOptions, type MintAndCashOutRequest, type MintAndCashOutResponse, type MintEvent, MintingGateway, type MintingGatewayConfig, MintingGatewayError, type MintingGatewayErrorCode, type MintingStatus, NonceManager, type OperatorWalletLike, PAFI_ISSUER_SDK_VERSION, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, PrivateKeySigner, type PrivateKeySignerOptions, RelayError, type RelayErrorCode, type RelayResult, RelayService, type RelayServiceConfig, type Session, type SponsorshipRequest, type SponsorshipResponse, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, type SubmitMintAndSwapParams, TopUpRedemptionError, TopUpRedemptionHandler, type TopUpRedemptionHandlerConfig, type TopUpRedemptionRequest, type TopUpRedemptionResponse, authenticateRequest, createIssuerService, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Address, Hex, PublicClient, Chain } from 'viem';
2
- import { PointTokenDomainConfig, MintRequest, EIP712Signature, MintParams, SwapParams, ReceiverConsent, PathKey, PoolKey, SponsorshipScenario, PartialUserOperation } from '@pafi-dev/core';
2
+ import { PointTokenDomainConfig, MintRequest, EIP712Signature, MintParams, SwapParams, MintRequestV2, SignatureStruct, PartialUserOperation, BurnConsent, ReceiverConsent, PathKey, PoolKey, SponsorshipScenario } from '@pafi-dev/core';
3
3
  export { encodeExtData } from '@pafi-dev/core';
4
4
 
5
5
  /**
@@ -565,6 +565,75 @@ declare class RelayService {
565
565
  * can ship (blocker B1). Kept for v0.2.x consumers. Removed in 2.0.
566
566
  */
567
567
  submitMintAndSwap(params: SubmitMintAndSwapParams): Promise<RelayResult>;
568
+ /**
569
+ * Build an unsigned UserOp for Scenario 1 (Mint).
570
+ *
571
+ * Flow:
572
+ * 1. Encode `Relayer.mint(request, userSig, issuerSig)` as the inner call
573
+ * 2. Optionally append a PT fee transfer from user → feeRecipient
574
+ * (fee recovery happens on-chain via BatchExecutor, not via an
575
+ * operator wallet)
576
+ * 3. Wrap all inner calls into `BatchExecutor.execute(calls[])`
577
+ * 4. Return a `PartialUserOperation` ready for:
578
+ * - gas estimation (Bundler)
579
+ * - paymaster sponsorship (PAFI Backend)
580
+ * - user signature (Privy)
581
+ */
582
+ prepareMint(params: PrepareMintParams): PartialUserOperation;
583
+ /**
584
+ * Build an unsigned UserOp for Scenario 2 (Burn/Redeem).
585
+ *
586
+ * Two modes:
587
+ * - `mode: 'burn'` — direct `PointToken.burn(amount)`; `msg.sender`
588
+ * via EIP-7702 delegation is the user, so no signature needed
589
+ * on-chain (the BurnConsent was already verified off-chain by
590
+ * the issuer backend before we got here)
591
+ * - `mode: 'burnWithSig'` — `PointToken.burnWithSig(consent, sig)`;
592
+ * used when the issuer hasn't verified the consent and the
593
+ * contract has to do it on-chain
594
+ */
595
+ prepareBurn(params: PrepareBurnParams): PartialUserOperation;
596
+ }
597
+ interface PrepareMintParams {
598
+ /** User EOA that will send the UserOp (via EIP-7702 delegation). */
599
+ userAddress: Address;
600
+ /** ERC-4337 account nonce (not the MintRequest nonce — different namespace). */
601
+ aaNonce: bigint;
602
+ /** Deployed Relayer v2 contract address (chain-specific). */
603
+ relayerAddress: Address;
604
+ /** BatchExecutor delegation target (chain-specific). */
605
+ batchExecutorAddress: Address;
606
+ /** PointToken being minted — used for optional fee transfer call. */
607
+ pointTokenAddress: Address;
608
+ /** EIP-712-signed MintRequest fields. */
609
+ mintRequest: MintRequestV2;
610
+ /** User's EIP-712 signature over `mintRequest`. */
611
+ userSignature: SignatureStruct;
612
+ /** Issuer's EIP-712 signature over `mintRequest`. */
613
+ issuerSignature: SignatureStruct;
614
+ /** Gas limits — defaults are conservative; caller can tighten. */
615
+ callGasLimit?: bigint;
616
+ verificationGasLimit?: bigint;
617
+ preVerificationGas?: bigint;
618
+ }
619
+ type PrepareBurnParams = PrepareBurnDirectParams | PrepareBurnWithSigParams;
620
+ interface PrepareBurnCommonParams {
621
+ userAddress: Address;
622
+ aaNonce: bigint;
623
+ pointTokenAddress: Address;
624
+ batchExecutorAddress: Address;
625
+ callGasLimit?: bigint;
626
+ verificationGasLimit?: bigint;
627
+ preVerificationGas?: bigint;
628
+ }
629
+ interface PrepareBurnDirectParams extends PrepareBurnCommonParams {
630
+ mode: "burn";
631
+ amount: bigint;
632
+ }
633
+ interface PrepareBurnWithSigParams extends PrepareBurnCommonParams {
634
+ mode: "burnWithSig";
635
+ burnConsent: BurnConsent;
636
+ consentSignature: SignatureStruct;
568
637
  }
569
638
 
570
639
  interface FeeManagerConfig {
@@ -1260,6 +1329,143 @@ declare class IssuerApiHandlers {
1260
1329
  handleClaimAndSwap(userAddress: Address, request: ApiClaimAndSwapRequest): Promise<ApiClaimAndSwapResponse>;
1261
1330
  }
1262
1331
 
1332
+ /**
1333
+ * v1.4 reverse flow — **Variant A**: user-initiated PT redeem.
1334
+ *
1335
+ * User has on-chain PT, wants to convert back to off-chain points. They
1336
+ * sign a `BurnConsent`, the issuer backend verifies it, reserves an
1337
+ * off-chain credit, and returns an unsigned UserOp that the frontend
1338
+ * submits via the Bundler. When the burn lands, the `BurnIndexer`
1339
+ * (elsewhere) resolves the credit.
1340
+ *
1341
+ * **Mocked SC contracts** — this handler compiles + wires end-to-end
1342
+ * against `@pafi-dev/core/contracts` mock ABIs. When SC ships real
1343
+ * ABIs, no changes here — only `contracts/index.ts` re-export flips.
1344
+ */
1345
+ interface PTRedeemHandlerConfig {
1346
+ ledger: IPointLedger;
1347
+ relayService: RelayService;
1348
+ provider: PublicClient;
1349
+ /** PointToken contract address (chain-specific). */
1350
+ pointTokenAddress: Address;
1351
+ /** BatchExecutor delegation target (chain-specific). */
1352
+ batchExecutorAddress: Address;
1353
+ /** Chain id — used for domain separator when verifying BurnConsent. */
1354
+ chainId: number;
1355
+ /**
1356
+ * EIP-712 domain fields. Must match the on-chain PointToken's domain
1357
+ * separator exactly, or signature verification fails. `name` is
1358
+ * typically the PointToken's ERC-20 name (e.g. "PAFI Starbucks
1359
+ * Points"). `verifyingContract` defaults to `pointTokenAddress`.
1360
+ */
1361
+ domain: {
1362
+ name: string;
1363
+ verifyingContract?: Address;
1364
+ };
1365
+ /**
1366
+ * How long the pending credit stays reserved if the burn never lands.
1367
+ * Default: 15 min — long enough for a bundler submission + confirmation.
1368
+ */
1369
+ redeemLockDurationMs?: number;
1370
+ /** Clock injection for tests; defaults to `Date.now`. */
1371
+ now?: () => number;
1372
+ }
1373
+ interface PTRedeemRequest {
1374
+ userAddress: Address;
1375
+ amount: bigint;
1376
+ /** Serialized EIP-712 signature over the BurnConsent. */
1377
+ consentSignature: Hex;
1378
+ consent: BurnConsent;
1379
+ /** ERC-4337 account nonce for the user's EOA. */
1380
+ aaNonce: bigint;
1381
+ }
1382
+ interface PTRedeemResponse {
1383
+ /** Lock id from the ledger — client polls status with this. */
1384
+ lockId: string;
1385
+ /** Unsigned UserOp — FE attaches paymaster + user signature + submits. */
1386
+ userOp: PartialUserOperation;
1387
+ /** Seconds until the lock expires if the burn doesn't land. */
1388
+ expiresInSeconds: number;
1389
+ }
1390
+ declare class PTRedeemError extends Error {
1391
+ code: "INVALID_CONSENT" | "SIGNATURE_MISMATCH" | "AMOUNT_MISMATCH" | "EXPIRED_CONSENT" | "LEDGER_NOT_SUPPORTED";
1392
+ constructor(code: "INVALID_CONSENT" | "SIGNATURE_MISMATCH" | "AMOUNT_MISMATCH" | "EXPIRED_CONSENT" | "LEDGER_NOT_SUPPORTED", message: string);
1393
+ }
1394
+ declare class PTRedeemHandler {
1395
+ private readonly ledger;
1396
+ private readonly relayService;
1397
+ private readonly pointTokenAddress;
1398
+ private readonly batchExecutorAddress;
1399
+ private readonly chainId;
1400
+ private readonly domain;
1401
+ private readonly redeemLockDurationMs;
1402
+ private readonly now;
1403
+ constructor(config: PTRedeemHandlerConfig);
1404
+ handle(request: PTRedeemRequest): Promise<PTRedeemResponse>;
1405
+ }
1406
+
1407
+ /**
1408
+ * v1.4 reverse flow — **Variant B**: auto top-up on voucher redemption.
1409
+ *
1410
+ * User tries to redeem a voucher for `requiredAmount` off-chain points
1411
+ * but their off-chain balance is short. If their on-chain PT balance is
1412
+ * enough to cover the shortfall, this handler auto-triggers a burn for
1413
+ * exactly the shortfall amount so the voucher can proceed.
1414
+ *
1415
+ * Required off-chain: 500
1416
+ * Available off-chain: 300
1417
+ * Shortfall: 200
1418
+ * On-chain PT: 250 ← enough, top-up fires
1419
+ * → burn 200 PT, credit 200 off-chain, voucher proceeds with 500
1420
+ *
1421
+ * Delegates the actual burn construction to {@link PTRedeemHandler}
1422
+ * — this handler is pure business logic (calculating shortfall +
1423
+ * checking on-chain balance) on top.
1424
+ */
1425
+ interface TopUpRedemptionHandlerConfig {
1426
+ ledger: IPointLedger;
1427
+ ptRedeemHandler: PTRedeemHandler;
1428
+ provider: PublicClient;
1429
+ /** PointToken contract address (chain-specific). */
1430
+ pointTokenAddress: Address;
1431
+ }
1432
+ interface TopUpRedemptionRequest {
1433
+ userAddress: Address;
1434
+ /** Total points the voucher redemption requires off-chain. */
1435
+ requiredAmount: bigint;
1436
+ /**
1437
+ * The user's pre-signed `BurnConsent` + signature, prepared by the FE
1438
+ * with amount set to a worst-case upper bound. Handler inspects the
1439
+ * shortfall and uses the consent if the shortfall ≤ consent.amount.
1440
+ */
1441
+ redeemRequest: Pick<PTRedeemRequest, "consent" | "consentSignature" | "aaNonce">;
1442
+ }
1443
+ type TopUpRedemptionResponse = {
1444
+ action: "NO_TOP_UP_NEEDED";
1445
+ offChainBalance: bigint;
1446
+ } | {
1447
+ action: "INSUFFICIENT_ONCHAIN";
1448
+ offChainBalance: bigint;
1449
+ onChainBalance: bigint;
1450
+ shortfall: bigint;
1451
+ } | {
1452
+ action: "TOP_UP_STARTED";
1453
+ shortfall: bigint;
1454
+ redeem: PTRedeemResponse;
1455
+ };
1456
+ declare class TopUpRedemptionError extends Error {
1457
+ code: "INSUFFICIENT_ONCHAIN_BALANCE" | "CONSENT_AMOUNT_TOO_LOW" | "LEDGER_NOT_SUPPORTED";
1458
+ constructor(code: "INSUFFICIENT_ONCHAIN_BALANCE" | "CONSENT_AMOUNT_TOO_LOW" | "LEDGER_NOT_SUPPORTED", message: string);
1459
+ }
1460
+ declare class TopUpRedemptionHandler {
1461
+ private readonly ledger;
1462
+ private readonly ptRedeemHandler;
1463
+ private readonly provider;
1464
+ private readonly pointTokenAddress;
1465
+ constructor(config: TopUpRedemptionHandlerConfig);
1466
+ handle(request: TopUpRedemptionRequest): Promise<TopUpRedemptionResponse>;
1467
+ }
1468
+
1263
1469
  /**
1264
1470
  * Config for `createSubgraphPoolsProvider`.
1265
1471
  */
@@ -1716,4 +1922,4 @@ declare function createIssuerService(config: IssuerServiceConfig): IssuerService
1716
1922
  /** SDK package version — bumped on every release */
1717
1923
  declare const PAFI_ISSUER_SDK_VERSION = "0.1.0";
1718
1924
 
1719
- export { type ApiBuildConsentTypedDataRequest, type ApiBuildConsentTypedDataResponse, type ApiClaimAndSwapRequest, type ApiClaimAndSwapResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig, BalanceAggregator, type BalanceAggregatorConfig, type BurnEvent, BurnIndexer, type BurnIndexerConfig, type CombinedBalance, DefaultPolicyEngine, type DefaultPolicyEngineOptions, FeeManager, type FeeManagerConfig, type IIndexerCursorStore, type IIssuerSigner, type IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerService, type IssuerServiceConfig, type LockedMintRequest, type LoginResult, MemoryPointLedger, MemorySessionStore, type MemorySessionStoreOptions, type MintAndCashOutRequest, type MintAndCashOutResponse, type MintEvent, MintingGateway, type MintingGatewayConfig, MintingGatewayError, type MintingGatewayErrorCode, type MintingStatus, NonceManager, type OperatorWalletLike, PAFI_ISSUER_SDK_VERSION, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, PrivateKeySigner, type PrivateKeySignerOptions, RelayError, type RelayErrorCode, type RelayResult, RelayService, type RelayServiceConfig, type Session, type SponsorshipRequest, type SponsorshipResponse, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, type SubmitMintAndSwapParams, authenticateRequest, createIssuerService, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider };
1925
+ export { type ApiBuildConsentTypedDataRequest, type ApiBuildConsentTypedDataResponse, type ApiClaimAndSwapRequest, type ApiClaimAndSwapResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig, BalanceAggregator, type BalanceAggregatorConfig, type BurnEvent, BurnIndexer, type BurnIndexerConfig, type CombinedBalance, DefaultPolicyEngine, type DefaultPolicyEngineOptions, FeeManager, type FeeManagerConfig, type IIndexerCursorStore, type IIssuerSigner, type IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerService, type IssuerServiceConfig, type LockedMintRequest, type LoginResult, MemoryPointLedger, MemorySessionStore, type MemorySessionStoreOptions, type MintAndCashOutRequest, type MintAndCashOutResponse, type MintEvent, MintingGateway, type MintingGatewayConfig, MintingGatewayError, type MintingGatewayErrorCode, type MintingStatus, NonceManager, type OperatorWalletLike, PAFI_ISSUER_SDK_VERSION, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, PrivateKeySigner, type PrivateKeySignerOptions, RelayError, type RelayErrorCode, type RelayResult, RelayService, type RelayServiceConfig, type Session, type SponsorshipRequest, type SponsorshipResponse, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, type SubmitMintAndSwapParams, TopUpRedemptionError, TopUpRedemptionHandler, type TopUpRedemptionHandlerConfig, type TopUpRedemptionRequest, type TopUpRedemptionResponse, authenticateRequest, createIssuerService, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider };