@pafi-dev/issuer 0.3.0-beta.0 → 0.3.0-beta.10
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.cjs +134 -752
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +147 -508
- package/dist/index.d.ts +147 -508
- package/dist/index.js +128 -746
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Address, Hex, PublicClient, Chain } from 'viem';
|
|
2
|
-
import { PointTokenDomainConfig, MintRequest, EIP712Signature,
|
|
3
|
-
export { encodeExtData } from '@pafi-dev/core';
|
|
1
|
+
import { Address, Hex, PublicClient, Chain, WalletClient } from 'viem';
|
|
2
|
+
import { PointTokenDomainConfig, MintRequest, EIP712Signature, PartialUserOperation, BurnRequest, ReceiverConsent, PathKey, PoolKey } from '@pafi-dev/core';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Lifecycle of a minting request as tracked by the issuer's point ledger.
|
|
@@ -449,168 +448,93 @@ declare class AuthError extends Error {
|
|
|
449
448
|
}
|
|
450
449
|
|
|
451
450
|
/**
|
|
452
|
-
*
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
swap: SwapParams;
|
|
460
|
-
}
|
|
461
|
-
/**
|
|
462
|
-
* Result of a relay submission. `txHash` is returned immediately after
|
|
463
|
-
* the tx is broadcast; `receipt` is present only when the caller opted to
|
|
464
|
-
* wait for confirmation.
|
|
465
|
-
*/
|
|
466
|
-
interface RelayResult {
|
|
467
|
-
txHash: Hex;
|
|
468
|
-
blockNumber?: bigint;
|
|
469
|
-
gasUsed?: bigint;
|
|
470
|
-
status?: "success" | "reverted";
|
|
471
|
-
}
|
|
472
|
-
/**
|
|
473
|
-
* Errors raised by RelayService carry a `code` so the MintingGateway (or
|
|
474
|
-
* any caller) can decide whether to release the ledger lock.
|
|
451
|
+
* Errors raised by RelayService carry a `code` so callers (handlers /
|
|
452
|
+
* gateway-less HTTP wrappers) can decide how to map them to HTTP status.
|
|
453
|
+
*
|
|
454
|
+
* v1.4 trimmed the error space to just encoding failures — the service
|
|
455
|
+
* no longer broadcasts transactions, so `SUBMIT_FAILED`, `TX_REVERTED`,
|
|
456
|
+
* `SIMULATION_FAILED`, and `TIMEOUT` all went away with the operator
|
|
457
|
+
* wallet. Paymaster/Bundler errors surface out-of-band on the FE.
|
|
475
458
|
*/
|
|
476
|
-
type RelayErrorCode = "NOT_CONFIGURED" | "ENCODE_FAILED"
|
|
459
|
+
type RelayErrorCode = "NOT_CONFIGURED" | "ENCODE_FAILED";
|
|
477
460
|
declare class RelayError extends Error {
|
|
478
461
|
readonly code: RelayErrorCode;
|
|
479
462
|
readonly cause?: unknown;
|
|
480
463
|
constructor(code: RelayErrorCode, message: string, cause?: unknown);
|
|
481
464
|
}
|
|
482
|
-
/**
|
|
483
|
-
* Interface an operator wallet must satisfy for the RelayService. Matches
|
|
484
|
-
* the subset of viem's `WalletClient` we actually call, so tests can pass
|
|
485
|
-
* a minimal mock instead of a full client.
|
|
486
|
-
*/
|
|
487
|
-
interface OperatorWalletLike {
|
|
488
|
-
writeContract: (args: {
|
|
489
|
-
address: Address;
|
|
490
|
-
abi: readonly unknown[];
|
|
491
|
-
functionName: string;
|
|
492
|
-
args: readonly unknown[];
|
|
493
|
-
account?: {
|
|
494
|
-
address: Address;
|
|
495
|
-
};
|
|
496
|
-
}) => Promise<Hex>;
|
|
497
|
-
account?: {
|
|
498
|
-
address: Address;
|
|
499
|
-
} | undefined;
|
|
500
|
-
}
|
|
501
465
|
|
|
502
|
-
interface RelayServiceConfig {
|
|
503
|
-
/** Address of the deployed Relay contract (chain-specific). */
|
|
504
|
-
relayAddress: Address;
|
|
505
|
-
/** Operator wallet that pays gas and receives the operator fee. */
|
|
506
|
-
operatorWallet: OperatorWalletLike;
|
|
507
|
-
/**
|
|
508
|
-
* Provider used for pre-flight simulation and receipt waiting. Optional —
|
|
509
|
-
* if omitted, the service still broadcasts but returns only `txHash`
|
|
510
|
-
* (caller is responsible for confirmation tracking).
|
|
511
|
-
*/
|
|
512
|
-
provider?: PublicClient;
|
|
513
|
-
/**
|
|
514
|
-
* If a provider is supplied, wait up to this many milliseconds for a
|
|
515
|
-
* receipt before timing out. Default: 60_000 (one minute).
|
|
516
|
-
*/
|
|
517
|
-
confirmationTimeoutMs?: number;
|
|
518
|
-
/**
|
|
519
|
-
* Whether to run `simulateContract` before submitting. Catches most
|
|
520
|
-
* reverts locally without wasting gas. Default: true (when provider is
|
|
521
|
-
* supplied).
|
|
522
|
-
*/
|
|
523
|
-
simulateBeforeSubmit?: boolean;
|
|
524
|
-
}
|
|
525
466
|
/**
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
* MintingGateway calls into `submitMintAndSwap()` after it has signed the
|
|
529
|
-
* MintRequest and verified the ReceiverConsent.
|
|
467
|
+
* Builds unsigned `PartialUserOperation` payloads for the v1.4 sponsored
|
|
468
|
+
* flow. The service is stateless and HTTP-client-free:
|
|
530
469
|
*
|
|
531
|
-
*
|
|
532
|
-
*
|
|
533
|
-
*
|
|
470
|
+
* - `prepareMint` signs a `MintRequest` EIP-712 with the caller-supplied
|
|
471
|
+
* issuer signer wallet, then encodes `PointToken.mint(to, amount,
|
|
472
|
+
* deadline, minterSig)` into a UserOp the frontend submits via
|
|
473
|
+
* EIP-7702 + Paymaster.
|
|
474
|
+
* - `prepareBurn` mirrors the above on the burn side using a
|
|
475
|
+
* pre-signed `BurnRequest` + `PointToken.burn(from, amount,
|
|
476
|
+
* deadline, burnerSig)`.
|
|
477
|
+
*
|
|
478
|
+
* There is no broadcasting, no operator wallet, no simulation — those
|
|
479
|
+
* concerns moved to the Bundler + Paymaster in v1.4.
|
|
534
480
|
*/
|
|
535
481
|
declare class RelayService {
|
|
536
|
-
private readonly relayAddress;
|
|
537
|
-
private readonly operatorWallet;
|
|
538
|
-
private readonly provider?;
|
|
539
|
-
private readonly confirmationTimeoutMs;
|
|
540
|
-
private readonly simulateBeforeSubmit;
|
|
541
|
-
constructor(config: RelayServiceConfig);
|
|
542
|
-
/** Address the operator wallet is broadcasting from (for logging). */
|
|
543
|
-
operatorAddress(): Address | undefined;
|
|
544
482
|
/**
|
|
545
|
-
* Build
|
|
546
|
-
*
|
|
547
|
-
* for audit before broadcasting.
|
|
483
|
+
* Build an unsigned UserOp for Scenario 1 (Mint) — sig-gated
|
|
484
|
+
* `PointToken.mint(to, amount, deadline, minterSig)`.
|
|
548
485
|
*/
|
|
549
|
-
|
|
550
|
-
/**
|
|
551
|
-
* Submit a `mintAndSwap` transaction. Flow:
|
|
552
|
-
*
|
|
553
|
-
* 1. (optional) pre-flight simulate via provider
|
|
554
|
-
* 2. writeContract through the operator wallet
|
|
555
|
-
* 3. (optional) wait for the receipt and surface gasUsed / status
|
|
556
|
-
*
|
|
557
|
-
* Throws a typed `RelayError` on any failure so the MintingGateway can
|
|
558
|
-
* decide whether to release the ledger lock (`SUBMIT_FAILED` and
|
|
559
|
-
* `SIMULATION_FAILED` are safe to release; `TX_REVERTED` and `TIMEOUT`
|
|
560
|
-
* need manual review because the tx may still land).
|
|
561
|
-
*
|
|
562
|
-
* @deprecated Since 0.3.0 — will be replaced by `prepareMint()` +
|
|
563
|
-
* `prepareBurn()` in the v1.4 sponsored-UserOp flow. The SC team
|
|
564
|
-
* still needs to finalize Relayer v2 ABI before the replacements
|
|
565
|
-
* can ship (blocker B1). Kept for v0.2.x consumers. Removed in 2.0.
|
|
566
|
-
*/
|
|
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;
|
|
486
|
+
prepareMint(params: PrepareMintParams): Promise<PartialUserOperation>;
|
|
583
487
|
/**
|
|
584
488
|
* Build an unsigned UserOp for Scenario 2 (Burn/Redeem).
|
|
585
489
|
*
|
|
586
490
|
* Two modes:
|
|
587
|
-
* - `mode: 'burn'` — direct `PointToken.burn(amount)`;
|
|
588
|
-
* via EIP-7702
|
|
589
|
-
*
|
|
590
|
-
*
|
|
591
|
-
*
|
|
592
|
-
*
|
|
593
|
-
* contract has to do it on-chain
|
|
491
|
+
* - `mode: 'burn'` — direct `PointToken.burn(from, amount)`; only
|
|
492
|
+
* usable if the caller (via EIP-7702) is whitelisted as a burner.
|
|
493
|
+
* Rare in v1.4; kept for admin/operator tools.
|
|
494
|
+
* - `mode: 'burnWithSig'` — `PointToken.burn(from, amount, deadline,
|
|
495
|
+
* burnerSig)`. Caller provides a pre-signed `BurnRequest` + sig
|
|
496
|
+
* bytes (typically from `PTRedeemHandler`).
|
|
594
497
|
*/
|
|
595
498
|
prepareBurn(params: PrepareBurnParams): PartialUserOperation;
|
|
596
499
|
}
|
|
500
|
+
/**
|
|
501
|
+
* v1.4 — sig-gated `PointToken.mint(to, amount, deadline, minterSig)`.
|
|
502
|
+
*
|
|
503
|
+
* The issuer backend validates off-chain (balance, policy, KYC), signs
|
|
504
|
+
* a `MintRequest` EIP-712 with its minter signer, and packages the
|
|
505
|
+
* whole thing into a UserOp for the user to submit via EIP-7702 +
|
|
506
|
+
* Paymaster. On confirmation, PointIndexer watches `Transfer(0x0, user,
|
|
507
|
+
* amount)` and resolves the ledger lock.
|
|
508
|
+
*/
|
|
597
509
|
interface PrepareMintParams {
|
|
598
510
|
/** User EOA that will send the UserOp (via EIP-7702 delegation). */
|
|
599
511
|
userAddress: Address;
|
|
600
|
-
/** ERC-4337 account nonce
|
|
512
|
+
/** ERC-4337 account nonce. Caller fetches from EntryPoint v0.7. */
|
|
601
513
|
aaNonce: bigint;
|
|
602
|
-
/** Deployed Relayer v2 contract address (chain-specific). */
|
|
603
|
-
relayerAddress: Address;
|
|
604
514
|
/** BatchExecutor delegation target (chain-specific). */
|
|
605
515
|
batchExecutorAddress: Address;
|
|
606
|
-
/** PointToken
|
|
516
|
+
/** PointToken contract — the call target + EIP-712 verifying contract. */
|
|
607
517
|
pointTokenAddress: Address;
|
|
608
|
-
/**
|
|
609
|
-
|
|
610
|
-
/**
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
518
|
+
/** PT amount to mint to `userAddress`. */
|
|
519
|
+
amount: bigint;
|
|
520
|
+
/**
|
|
521
|
+
* Issuer minter signer wallet — signs the `MintRequest` EIP-712.
|
|
522
|
+
* Must be added to `PointToken.minters[]` via `addMinter(signerAddr)`
|
|
523
|
+
* at provisioning time. Typically HSM/KMS-backed in prod.
|
|
524
|
+
*/
|
|
525
|
+
issuerSignerWallet: WalletClient;
|
|
526
|
+
/** EIP-712 domain for MintRequest. */
|
|
527
|
+
domain: PointTokenDomainConfig;
|
|
528
|
+
/** Current `mintRequestNonces[userAddress]` — caller reads from contract. */
|
|
529
|
+
mintRequestNonce: bigint;
|
|
530
|
+
/** Unix timestamp after which the signature expires. */
|
|
531
|
+
deadline: bigint;
|
|
532
|
+
/**
|
|
533
|
+
* Optional — application-level fee transfer appended after mint.
|
|
534
|
+
* Set both `feeAmount` and `feeRecipient` together.
|
|
535
|
+
*/
|
|
536
|
+
feeAmount?: bigint;
|
|
537
|
+
feeRecipient?: Address;
|
|
614
538
|
/** Gas limits — defaults are conservative; caller can tighten. */
|
|
615
539
|
callGasLimit?: bigint;
|
|
616
540
|
verificationGasLimit?: bigint;
|
|
@@ -632,8 +556,10 @@ interface PrepareBurnDirectParams extends PrepareBurnCommonParams {
|
|
|
632
556
|
}
|
|
633
557
|
interface PrepareBurnWithSigParams extends PrepareBurnCommonParams {
|
|
634
558
|
mode: "burnWithSig";
|
|
635
|
-
|
|
636
|
-
|
|
559
|
+
/** BurnRequest message the issuer burner signer signed. */
|
|
560
|
+
burnRequest: BurnRequest;
|
|
561
|
+
/** Serialized EIP-712 signature (bytes) over `burnRequest`. */
|
|
562
|
+
burnerSignature: Hex;
|
|
637
563
|
}
|
|
638
564
|
|
|
639
565
|
interface FeeManagerConfig {
|
|
@@ -699,156 +625,6 @@ declare class FeeManager {
|
|
|
699
625
|
estimateGasFee(): Promise<bigint>;
|
|
700
626
|
}
|
|
701
627
|
|
|
702
|
-
/**
|
|
703
|
-
* End-user request for a full "burn points → receive USDT" flow. The
|
|
704
|
-
* receiver has already signed the `ReceiverConsent` EIP-712 message on
|
|
705
|
-
* the frontend; the issuer backend runs everything else.
|
|
706
|
-
*/
|
|
707
|
-
interface MintAndCashOutRequest {
|
|
708
|
-
/** Address owning the off-chain points (== receiver in the consent). */
|
|
709
|
-
userAddress: Address;
|
|
710
|
-
/** Point token contract to mint. */
|
|
711
|
-
pointTokenAddress: Address;
|
|
712
|
-
/** Chain id the relay will submit on. */
|
|
713
|
-
chainId: number;
|
|
714
|
-
/**
|
|
715
|
-
* EIP-712 domain for `pointTokenAddress`. The gateway passes this
|
|
716
|
-
* straight through to `@pafi/core` `verifyReceiverConsent` and the
|
|
717
|
-
* issuer signer. Callers typically fetch it once via
|
|
718
|
-
* `PafiSDK.getDomain()` and cache it.
|
|
719
|
-
*/
|
|
720
|
-
domain: PointTokenDomainConfig;
|
|
721
|
-
/**
|
|
722
|
-
* Receiver consent message + signature, pre-built by the frontend. The
|
|
723
|
-
* message specifies `onBehalfOf = relay contract` and
|
|
724
|
-
* `originalReceiver = userAddress`, plus the amount, nonce, deadline,
|
|
725
|
-
* and encoded extData.
|
|
726
|
-
*/
|
|
727
|
-
receiverConsent: ReceiverConsent;
|
|
728
|
-
receiverSignature: Hex;
|
|
729
|
-
/**
|
|
730
|
-
* Swap path for the USDT output. Empty array = "no swap" (rare — only
|
|
731
|
-
* useful for testing). Normally a single hop pointToken → USDT.
|
|
732
|
-
*/
|
|
733
|
-
swapPath: PathKey[];
|
|
734
|
-
/** Swap deadline (unix seconds). */
|
|
735
|
-
swapDeadline: bigint;
|
|
736
|
-
/**
|
|
737
|
-
* Lock TTL (ms) to apply to the off-chain balance. The gateway computes
|
|
738
|
-
* a safe default from `receiverConsent.deadline` if omitted.
|
|
739
|
-
*/
|
|
740
|
-
lockDurationMs?: number;
|
|
741
|
-
}
|
|
742
|
-
/**
|
|
743
|
-
* Result returned to the caller after a successful `processMintAndCashOut`.
|
|
744
|
-
* The `lockId` is preserved so the indexer can correlate the on-chain
|
|
745
|
-
* Mint event back to the ledger row (though that correlation is typically
|
|
746
|
-
* done by `(userAddress, amount)` in the default `MemoryPointLedger`).
|
|
747
|
-
*/
|
|
748
|
-
interface MintAndCashOutResponse {
|
|
749
|
-
txHash: Hex;
|
|
750
|
-
lockId: string;
|
|
751
|
-
blockNumber?: bigint;
|
|
752
|
-
gasUsed?: bigint;
|
|
753
|
-
}
|
|
754
|
-
/**
|
|
755
|
-
* Error codes a MintingGateway can surface. Callers (API handlers) map
|
|
756
|
-
* these to HTTP status codes. The `SAFE_TO_RETRY` field tells the caller
|
|
757
|
-
* whether the underlying lock was released — if not, the user should
|
|
758
|
-
* wait before retrying to avoid double-spend.
|
|
759
|
-
*/
|
|
760
|
-
type MintingGatewayErrorCode = "INVALID_REQUEST" | "INVALID_CONSENT_SIGNATURE" | "CONSENT_EXPIRED" | "POLICY_REJECTED" | "INSUFFICIENT_BALANCE" | "SIGNER_FAILED" | "RELAY_SIMULATION_FAILED" | "RELAY_SUBMIT_FAILED" | "RELAY_REVERTED" | "RELAY_TIMEOUT";
|
|
761
|
-
declare class MintingGatewayError extends Error {
|
|
762
|
-
readonly code: MintingGatewayErrorCode;
|
|
763
|
-
/**
|
|
764
|
-
* True if the ledger lock was released before this error was thrown,
|
|
765
|
-
* meaning the user can safely retry. False means the funds are still
|
|
766
|
-
* locked (e.g. tx may still land on-chain) and retry would double-spend.
|
|
767
|
-
*/
|
|
768
|
-
readonly safeToRetry: boolean;
|
|
769
|
-
readonly cause?: unknown;
|
|
770
|
-
constructor(code: MintingGatewayErrorCode, message: string, opts: {
|
|
771
|
-
safeToRetry: boolean;
|
|
772
|
-
cause?: unknown;
|
|
773
|
-
});
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
interface MintingGatewayConfig {
|
|
777
|
-
ledger: IPointLedger;
|
|
778
|
-
policy: IPolicyEngine;
|
|
779
|
-
signer: IIssuerSigner;
|
|
780
|
-
relayService: RelayService;
|
|
781
|
-
/**
|
|
782
|
-
* Clock override for tests. Defaults to `() => Date.now()`. Used to
|
|
783
|
-
* compute safe lock TTLs and to check consent deadlines.
|
|
784
|
-
*/
|
|
785
|
-
now?: () => number;
|
|
786
|
-
/**
|
|
787
|
-
* Extra buffer (ms) added on top of `(consent.deadline - now)` when the
|
|
788
|
-
* caller doesn't supply a `lockDurationMs`. Default: 60_000 (one minute
|
|
789
|
-
* — roughly 2× the Base L2 block confirmation time).
|
|
790
|
-
*/
|
|
791
|
-
defaultLockBufferMs?: number;
|
|
792
|
-
}
|
|
793
|
-
/**
|
|
794
|
-
* The MintingGateway is the central orchestrator that turns a user's
|
|
795
|
-
* signed ReceiverConsent into an on-chain `mintAndSwap` tx and a
|
|
796
|
-
* consistent off-chain ledger update.
|
|
797
|
-
*
|
|
798
|
-
* 11-step flow (per `PAFI_ISSUER_SDK_SPEC.md` §4.3):
|
|
799
|
-
*
|
|
800
|
-
* 1. Field validation (cheap rejects before any crypto)
|
|
801
|
-
* 2. Verify ReceiverConsent signature via `@pafi/core`
|
|
802
|
-
* 3. Check off-chain balance via ledger
|
|
803
|
-
* 4. Check locked requests via ledger
|
|
804
|
-
* 5. Run policy engine (balance + on-chain cap + issuer rules)
|
|
805
|
-
* 6. Lock the requested amount in the ledger
|
|
806
|
-
* 7. Sign MintRequest as issuer
|
|
807
|
-
* 8. Build MintParams + SwapParams
|
|
808
|
-
* 9. Submit via RelayService (encode + simulate + broadcast + wait)
|
|
809
|
-
* 10. Return { txHash, lockId, receipt fields }
|
|
810
|
-
* 11. On any failure, release the lock IF it's safe to retry — i.e. we
|
|
811
|
-
* know the tx cannot still land on-chain. If the tx may have made
|
|
812
|
-
* it (`TX_REVERTED` or `TIMEOUT`), we leave the lock alone and
|
|
813
|
-
* surface `safeToRetry: false` so the caller doesn't double-spend.
|
|
814
|
-
*
|
|
815
|
-
* The gateway deliberately does NOT deduct the balance here. Deduction
|
|
816
|
-
* happens in the `PointIndexer` when the on-chain Mint event is observed,
|
|
817
|
-
* which is what makes the system crash-safe: if the gateway dies between
|
|
818
|
-
* broadcast and receipt, the indexer will still finalize the ledger.
|
|
819
|
-
*/
|
|
820
|
-
declare class MintingGateway {
|
|
821
|
-
private readonly ledger;
|
|
822
|
-
private readonly policy;
|
|
823
|
-
private readonly signer;
|
|
824
|
-
private readonly relayService;
|
|
825
|
-
private readonly now;
|
|
826
|
-
private readonly defaultLockBufferMs;
|
|
827
|
-
constructor(config: MintingGatewayConfig);
|
|
828
|
-
/**
|
|
829
|
-
* @deprecated Since 0.3.0 — will be renamed to `processMint()` once
|
|
830
|
-
* the SC team finalizes Relayer v2 ABI. The new flow drops the
|
|
831
|
-
* swap steps entirely (no more single-call mint+swap); users swap
|
|
832
|
-
* separately on PAFI Web. Kept here for v0.2.x consumers. Removed in 2.0.
|
|
833
|
-
*/
|
|
834
|
-
processMintAndCashOut(request: MintAndCashOutRequest): Promise<MintAndCashOutResponse>;
|
|
835
|
-
private computeLockDurationMs;
|
|
836
|
-
/**
|
|
837
|
-
* Map a RelayError to a MintingGatewayError, releasing the lock only
|
|
838
|
-
* when the tx definitely did not land. `TX_REVERTED` and `TIMEOUT`
|
|
839
|
-
* leave the lock in place because the tx may still be in the mempool
|
|
840
|
-
* or already mined — releasing would enable a double-spend on retry.
|
|
841
|
-
* Always throws.
|
|
842
|
-
*/
|
|
843
|
-
private handleRelayFailure;
|
|
844
|
-
/**
|
|
845
|
-
* Release a lock, swallowing any secondary error. We never want a lock
|
|
846
|
-
* release failure to mask the original error — the lock will auto-expire
|
|
847
|
-
* via TTL anyway.
|
|
848
|
-
*/
|
|
849
|
-
private releaseLockSafely;
|
|
850
|
-
}
|
|
851
|
-
|
|
852
628
|
/** Decoded Transfer(from=0x0 → to) event used to finalize a mint. */
|
|
853
629
|
interface MintEvent {
|
|
854
630
|
/** Destination address (the user who received the minted points) */
|
|
@@ -1093,6 +869,18 @@ interface ApiConfigResponse {
|
|
|
1093
869
|
mintingOracle?: Address;
|
|
1094
870
|
poolManager?: Address;
|
|
1095
871
|
usdt?: Address;
|
|
872
|
+
/**
|
|
873
|
+
* EIP-7702 delegation target — the single contract every user's
|
|
874
|
+
* EOA must delegate to before submitting sponsored UserOps. On
|
|
875
|
+
* Base mainnet this is Coinbase Smart Wallet v2.
|
|
876
|
+
*/
|
|
877
|
+
batchExecutor?: Address;
|
|
878
|
+
/**
|
|
879
|
+
* Uniswap V4 hook that enforces the 10% fee on PT→USDT swaps
|
|
880
|
+
* (USDT→PT is free). FE uses this in `PoolKey.hooks` when building
|
|
881
|
+
* a swap; the pool is only discoverable when the hook matches.
|
|
882
|
+
*/
|
|
883
|
+
pafiHook?: Address;
|
|
1096
884
|
};
|
|
1097
885
|
/**
|
|
1098
886
|
* Absolute URL that the Issuer App opens after a successful claim to
|
|
@@ -1211,7 +999,6 @@ type PoolsProvider = (request: ApiPoolsRequest) => Promise<ApiPoolsResponse>;
|
|
|
1211
999
|
|
|
1212
1000
|
interface IssuerApiHandlersConfig {
|
|
1213
1001
|
authService: AuthService;
|
|
1214
|
-
gateway: MintingGateway;
|
|
1215
1002
|
ledger: IPointLedger;
|
|
1216
1003
|
/** Used by `handleUser` to read on-chain nonces and minter status. */
|
|
1217
1004
|
provider: PublicClient;
|
|
@@ -1242,8 +1029,7 @@ interface IssuerApiHandlersConfig {
|
|
|
1242
1029
|
* Framework-agnostic HTTP handlers that match the endpoints a `PafiSDK`
|
|
1243
1030
|
* frontend expects to call. Issuers wrap these in Express / Fastify /
|
|
1244
1031
|
* Hono / whatever — the handlers take plain inputs and return plain
|
|
1245
|
-
* outputs, with `AuthError`
|
|
1246
|
-
* exceptions.
|
|
1032
|
+
* outputs, with `AuthError` surfaced as typed exceptions.
|
|
1247
1033
|
*
|
|
1248
1034
|
* Every protected handler takes a pre-verified `userAddress` as its first
|
|
1249
1035
|
* argument. The issuer's middleware wraps `authenticateRequest()` from
|
|
@@ -1252,7 +1038,6 @@ interface IssuerApiHandlersConfig {
|
|
|
1252
1038
|
*/
|
|
1253
1039
|
declare class IssuerApiHandlers {
|
|
1254
1040
|
private readonly authService;
|
|
1255
|
-
private readonly gateway;
|
|
1256
1041
|
private readonly ledger;
|
|
1257
1042
|
private readonly provider;
|
|
1258
1043
|
/**
|
|
@@ -1314,33 +1099,32 @@ declare class IssuerApiHandlers {
|
|
|
1314
1099
|
* mobile apps — no app store review needed.
|
|
1315
1100
|
*/
|
|
1316
1101
|
handleBuildConsentTypedData(userAddress: Address, request: ApiBuildConsentTypedDataRequest): Promise<ApiBuildConsentTypedDataResponse>;
|
|
1317
|
-
/**
|
|
1318
|
-
* `POST /claim-and-swap`
|
|
1319
|
-
*
|
|
1320
|
-
* @deprecated Since 0.3.0 — the single-call mint-then-swap flow is
|
|
1321
|
-
* retired in v1.4. Use the new `handleClaim()` (mint only) and let
|
|
1322
|
-
* the user swap separately on PAFI Web. See
|
|
1323
|
-
* [V1.4_V1.5_OVERVIEW.md §4] for the new scenario model. Will be
|
|
1324
|
-
* removed in 2.0.
|
|
1325
|
-
*
|
|
1326
|
-
* Legacy behavior: the terminal handler forwards the verified
|
|
1327
|
-
* consent to the MintingGateway, which runs the 11-step flow.
|
|
1328
|
-
*/
|
|
1329
|
-
handleClaimAndSwap(userAddress: Address, request: ApiClaimAndSwapRequest): Promise<ApiClaimAndSwapResponse>;
|
|
1330
1102
|
}
|
|
1331
1103
|
|
|
1332
1104
|
/**
|
|
1333
|
-
* v1.4 reverse flow —
|
|
1105
|
+
* v1.4 reverse flow — user-initiated PT redeem.
|
|
1106
|
+
*
|
|
1107
|
+
* User has on-chain PT, wants to convert back to off-chain points. The
|
|
1108
|
+
* issuer backend signs a `BurnRequest` with its burner signer, reserves
|
|
1109
|
+
* an off-chain pending credit, and returns an unsigned UserOp. The FE
|
|
1110
|
+
* submits the UserOp via EIP-7702 + Coinbase Paymaster. On confirmation,
|
|
1111
|
+
* `Transfer(user → 0x0)` is emitted; `BurnIndexer` resolves the pending
|
|
1112
|
+
* credit to a real off-chain credit.
|
|
1334
1113
|
*
|
|
1335
|
-
*
|
|
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.
|
|
1114
|
+
* Contract path (mock ABI — matches deployed PointToken):
|
|
1340
1115
|
*
|
|
1341
|
-
*
|
|
1342
|
-
*
|
|
1343
|
-
*
|
|
1116
|
+
* burn(address from, uint256 amount, uint256 deadline, bytes burnerSig)
|
|
1117
|
+
*
|
|
1118
|
+
* On-chain checks:
|
|
1119
|
+
* - msg.sender == from (enforced via EIP-7702 delegation on user EOA)
|
|
1120
|
+
* - burnerSig signer ∈ burners[]
|
|
1121
|
+
* - nonce == burnRequestNonces[from]
|
|
1122
|
+
* - now <= deadline
|
|
1123
|
+
*
|
|
1124
|
+
* The user never signs an EIP-712 message in this flow. Their only
|
|
1125
|
+
* signature is the ERC-4337 UserOp signature, which the AA wallet
|
|
1126
|
+
* handles. Consent is implicit: by submitting the UserOp they authorize
|
|
1127
|
+
* the burn.
|
|
1344
1128
|
*/
|
|
1345
1129
|
interface PTRedeemHandlerConfig {
|
|
1346
1130
|
ledger: IPointLedger;
|
|
@@ -1350,32 +1134,41 @@ interface PTRedeemHandlerConfig {
|
|
|
1350
1134
|
pointTokenAddress: Address;
|
|
1351
1135
|
/** BatchExecutor delegation target (chain-specific). */
|
|
1352
1136
|
batchExecutorAddress: Address;
|
|
1353
|
-
/** Chain id — used for
|
|
1137
|
+
/** Chain id — used for the BurnRequest EIP-712 domain. */
|
|
1354
1138
|
chainId: number;
|
|
1355
1139
|
/**
|
|
1356
1140
|
* EIP-712 domain fields. Must match the on-chain PointToken's domain
|
|
1357
|
-
* separator
|
|
1358
|
-
* typically the PointToken's ERC-20 name
|
|
1359
|
-
*
|
|
1141
|
+
* separator, or on-chain signature recovery fails. `name` is
|
|
1142
|
+
* typically the PointToken's ERC-20 name. `verifyingContract`
|
|
1143
|
+
* defaults to `pointTokenAddress`.
|
|
1360
1144
|
*/
|
|
1361
1145
|
domain: {
|
|
1362
1146
|
name: string;
|
|
1363
1147
|
verifyingContract?: Address;
|
|
1364
1148
|
};
|
|
1149
|
+
/**
|
|
1150
|
+
* Issuer burner signer wallet — signs the `BurnRequest` EIP-712.
|
|
1151
|
+
* Must be whitelisted via `PointToken.addBurner(signerAddr)` at
|
|
1152
|
+
* provisioning time. Typically HSM/KMS-backed in prod.
|
|
1153
|
+
*/
|
|
1154
|
+
burnerSignerWallet: WalletClient;
|
|
1365
1155
|
/**
|
|
1366
1156
|
* How long the pending credit stays reserved if the burn never lands.
|
|
1367
1157
|
* Default: 15 min — long enough for a bundler submission + confirmation.
|
|
1368
1158
|
*/
|
|
1369
1159
|
redeemLockDurationMs?: number;
|
|
1160
|
+
/**
|
|
1161
|
+
* How far ahead of `now` to set the BurnRequest deadline. Default:
|
|
1162
|
+
* 15 min. Must be long enough for Bundler + EntryPoint to execute;
|
|
1163
|
+
* short enough to prevent replay if the UserOp is abandoned.
|
|
1164
|
+
*/
|
|
1165
|
+
signatureDeadlineSeconds?: number;
|
|
1370
1166
|
/** Clock injection for tests; defaults to `Date.now`. */
|
|
1371
1167
|
now?: () => number;
|
|
1372
1168
|
}
|
|
1373
1169
|
interface PTRedeemRequest {
|
|
1374
1170
|
userAddress: Address;
|
|
1375
1171
|
amount: bigint;
|
|
1376
|
-
/** Serialized EIP-712 signature over the BurnConsent. */
|
|
1377
|
-
consentSignature: Hex;
|
|
1378
|
-
consent: BurnConsent;
|
|
1379
1172
|
/** ERC-4337 account nonce for the user's EOA. */
|
|
1380
1173
|
aaNonce: bigint;
|
|
1381
1174
|
}
|
|
@@ -1386,19 +1179,24 @@ interface PTRedeemResponse {
|
|
|
1386
1179
|
userOp: PartialUserOperation;
|
|
1387
1180
|
/** Seconds until the lock expires if the burn doesn't land. */
|
|
1388
1181
|
expiresInSeconds: number;
|
|
1182
|
+
/** The BurnRequest deadline (unix seconds) — FE uses this to surface a countdown. */
|
|
1183
|
+
signatureDeadline: bigint;
|
|
1389
1184
|
}
|
|
1390
1185
|
declare class PTRedeemError extends Error {
|
|
1391
|
-
code: "
|
|
1392
|
-
constructor(code: "
|
|
1186
|
+
code: "INVALID_AMOUNT" | "NONCE_READ_FAILED" | "LEDGER_NOT_SUPPORTED" | "SIGNING_FAILED";
|
|
1187
|
+
constructor(code: "INVALID_AMOUNT" | "NONCE_READ_FAILED" | "LEDGER_NOT_SUPPORTED" | "SIGNING_FAILED", message: string);
|
|
1393
1188
|
}
|
|
1394
1189
|
declare class PTRedeemHandler {
|
|
1395
1190
|
private readonly ledger;
|
|
1396
1191
|
private readonly relayService;
|
|
1192
|
+
private readonly provider;
|
|
1397
1193
|
private readonly pointTokenAddress;
|
|
1398
1194
|
private readonly batchExecutorAddress;
|
|
1399
1195
|
private readonly chainId;
|
|
1400
1196
|
private readonly domain;
|
|
1197
|
+
private readonly burnerSignerWallet;
|
|
1401
1198
|
private readonly redeemLockDurationMs;
|
|
1199
|
+
private readonly signatureDeadlineSeconds;
|
|
1402
1200
|
private readonly now;
|
|
1403
1201
|
constructor(config: PTRedeemHandlerConfig);
|
|
1404
1202
|
handle(request: PTRedeemRequest): Promise<PTRedeemResponse>;
|
|
@@ -1419,8 +1217,12 @@ declare class PTRedeemHandler {
|
|
|
1419
1217
|
* → burn 200 PT, credit 200 off-chain, voucher proceeds with 500
|
|
1420
1218
|
*
|
|
1421
1219
|
* Delegates the actual burn construction to {@link PTRedeemHandler}
|
|
1422
|
-
* — this handler is pure business logic (
|
|
1423
|
-
*
|
|
1220
|
+
* — this handler is pure business logic (shortfall math + on-chain
|
|
1221
|
+
* balance check) on top.
|
|
1222
|
+
*
|
|
1223
|
+
* v1.4 note: user no longer pre-signs a `BurnConsent`. The issuer
|
|
1224
|
+
* backend signs a `BurnRequest` itself (see `PTRedeemHandler`), so
|
|
1225
|
+
* this handler only needs `userAddress + requiredAmount + aaNonce`.
|
|
1424
1226
|
*/
|
|
1425
1227
|
interface TopUpRedemptionHandlerConfig {
|
|
1426
1228
|
ledger: IPointLedger;
|
|
@@ -1433,12 +1235,8 @@ interface TopUpRedemptionRequest {
|
|
|
1433
1235
|
userAddress: Address;
|
|
1434
1236
|
/** Total points the voucher redemption requires off-chain. */
|
|
1435
1237
|
requiredAmount: bigint;
|
|
1436
|
-
/**
|
|
1437
|
-
|
|
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">;
|
|
1238
|
+
/** ERC-4337 account nonce for the user's EOA. */
|
|
1239
|
+
aaNonce: bigint;
|
|
1442
1240
|
}
|
|
1443
1241
|
type TopUpRedemptionResponse = {
|
|
1444
1242
|
action: "NO_TOP_UP_NEEDED";
|
|
@@ -1454,8 +1252,8 @@ type TopUpRedemptionResponse = {
|
|
|
1454
1252
|
redeem: PTRedeemResponse;
|
|
1455
1253
|
};
|
|
1456
1254
|
declare class TopUpRedemptionError extends Error {
|
|
1457
|
-
code: "INSUFFICIENT_ONCHAIN_BALANCE" | "
|
|
1458
|
-
constructor(code: "INSUFFICIENT_ONCHAIN_BALANCE" | "
|
|
1255
|
+
code: "INSUFFICIENT_ONCHAIN_BALANCE" | "LEDGER_NOT_SUPPORTED";
|
|
1256
|
+
constructor(code: "INSUFFICIENT_ONCHAIN_BALANCE" | "LEDGER_NOT_SUPPORTED", message: string);
|
|
1459
1257
|
}
|
|
1460
1258
|
declare class TopUpRedemptionHandler {
|
|
1461
1259
|
private readonly ledger;
|
|
@@ -1640,185 +1438,52 @@ declare class BalanceAggregator {
|
|
|
1640
1438
|
}
|
|
1641
1439
|
|
|
1642
1440
|
interface RetryConfig {
|
|
1643
|
-
/**
|
|
1644
|
-
* Max total attempts including the first try. Default: 1 (no retry).
|
|
1645
|
-
* Set to 3 to get 2 retries after the initial call.
|
|
1646
|
-
*
|
|
1647
|
-
* Only applies when the server error body carries `safeToRetry: true`
|
|
1648
|
-
* or the failure is a transient network/timeout error.
|
|
1649
|
-
*/
|
|
1650
1441
|
maxAttempts?: number;
|
|
1651
|
-
/**
|
|
1652
|
-
* Initial backoff delay in ms. Default: 500. Each subsequent retry
|
|
1653
|
-
* doubles this (exponential backoff) and adds ±20% jitter.
|
|
1654
|
-
*/
|
|
1655
1442
|
initialDelayMs?: number;
|
|
1656
|
-
/**
|
|
1657
|
-
* Hard ceiling for a single backoff (ms). Default: 10_000.
|
|
1658
|
-
*/
|
|
1659
1443
|
maxDelayMs?: number;
|
|
1660
|
-
/**
|
|
1661
|
-
* Upper bound on `retryAfter` from the server. If the server asks us
|
|
1662
|
-
* to wait longer than this (e.g. rate limit until UTC midnight), the
|
|
1663
|
-
* client gives up rather than blocking. Default: 30_000.
|
|
1664
|
-
*/
|
|
1665
1444
|
maxRetryAfterMs?: number;
|
|
1666
1445
|
}
|
|
1667
1446
|
interface PafiBackendConfig {
|
|
1668
|
-
/**
|
|
1669
|
-
* PAFI Backend API base URL. Example:
|
|
1670
|
-
* https://api.pacificfinance.org
|
|
1671
|
-
* https://staging-api.pacificfinance.org
|
|
1672
|
-
*/
|
|
1673
1447
|
url: string;
|
|
1674
|
-
/** PAFI-assigned issuer ID (e.g., "gg56"). Sent in X-Issuer-Id header. */
|
|
1675
1448
|
issuerId: string;
|
|
1676
|
-
/** Per-issuer API key (or JWT) for the Authorization header. */
|
|
1677
1449
|
apiKey: string;
|
|
1678
|
-
/** Optional fetch override for tests. */
|
|
1679
1450
|
fetchImpl?: typeof fetch;
|
|
1680
|
-
/**
|
|
1681
|
-
* Timeout (ms) for each request. Default: 10_000. PAFI Backend should
|
|
1682
|
-
* respond in <1s for the happy path; this is just the sanity bound.
|
|
1683
|
-
*/
|
|
1684
1451
|
timeoutMs?: number;
|
|
1685
|
-
/**
|
|
1686
|
-
* Retry policy for transient failures (5xx, 429, timeouts, network).
|
|
1687
|
-
* Omit or pass `{ maxAttempts: 1 }` to disable retry entirely.
|
|
1688
|
-
*/
|
|
1689
1452
|
retry?: RetryConfig;
|
|
1690
1453
|
}
|
|
1691
|
-
|
|
1692
|
-
interface SponsorshipRequest {
|
|
1693
|
-
chainId: number;
|
|
1694
|
-
scenario: SponsorshipScenario;
|
|
1695
|
-
userOp: PartialUserOperation;
|
|
1696
|
-
target: {
|
|
1697
|
-
/** The allowlisted contract this batch call targets. */
|
|
1698
|
-
contract: Address;
|
|
1699
|
-
/** Function selector / name — validated against allowlist. */
|
|
1700
|
-
function: string;
|
|
1701
|
-
/** The PointToken involved (for scenario context). */
|
|
1702
|
-
pointToken?: Address;
|
|
1703
|
-
};
|
|
1704
|
-
}
|
|
1705
|
-
interface SponsorshipResponse {
|
|
1706
|
-
paymaster: Address;
|
|
1707
|
-
paymasterData: Hex;
|
|
1708
|
-
paymasterVerificationGasLimit: bigint;
|
|
1709
|
-
paymasterPostOpGasLimit: bigint;
|
|
1710
|
-
/** Unix seconds when this sponsorship expires. Re-request after. */
|
|
1711
|
-
expiresAt: number;
|
|
1712
|
-
}
|
|
1713
|
-
/**
|
|
1714
|
-
* Machine-readable error codes returned by PAFI Backend.
|
|
1715
|
-
*
|
|
1716
|
-
* Source of truth: `apps/paymaster-proxy` `CalldataValidationError`,
|
|
1717
|
-
* `RateLimitError`, `CoinbaseClientError`. Keep in sync.
|
|
1718
|
-
*/
|
|
1719
|
-
type PafiBackendErrorCode = "MISSING_ISSUER_ID" | "MISSING_API_KEY" | "ISSUER_UNAUTHORIZED" | "CALLDATA_INVALID" | "CALLDATA_EMPTY_BATCH" | "TARGET_NOT_ALLOWLISTED" | "FUNCTION_NOT_ALLOWED" | "SCENARIO_MISMATCH" | "SCENARIO_DISABLED" | "RATE_LIMIT_EXCEEDED" | "RATE_LIMIT_EXCEEDED_DAILY" | "RATE_LIMIT_EXCEEDED_PER_USER" | "RATE_LIMITER_UNAVAILABLE" | "PAYMASTER_REJECTED" | "PAYMASTER_UNAVAILABLE" | "PAYMASTER_TIMEOUT" | "BAD_REQUEST" | "INTERNAL_ERROR" | "TIMEOUT" | "NETWORK_ERROR";
|
|
1454
|
+
type PafiBackendErrorCode = "MISSING_ISSUER_ID" | "MISSING_API_KEY" | "ISSUER_UNAUTHORIZED" | "USER_UNAUTHORIZED" | "INTENT_REJECTED" | "MINT_CAP_EXCEEDED" | "ISSUER_INACTIVE" | "BROKER_NOT_WHITELISTED" | "RATE_LIMIT_EXCEEDED" | "RATE_LIMIT_EXCEEDED_DAILY" | "RATE_LIMIT_EXCEEDED_PER_USER" | "ISSUER_BUDGET_EXCEEDED" | "RATE_LIMITER_UNAVAILABLE" | "BAD_REQUEST" | "INTERNAL_ERROR" | "TIMEOUT" | "NETWORK_ERROR";
|
|
1720
1455
|
declare class PafiBackendError extends Error {
|
|
1721
1456
|
code: PafiBackendErrorCode;
|
|
1722
1457
|
httpStatus: number;
|
|
1723
1458
|
details?: unknown | undefined;
|
|
1724
|
-
/**
|
|
1725
|
-
* Seconds to wait before retry. Populated from the server body
|
|
1726
|
-
* (e.g. rate limit returns the number of seconds until UTC midnight).
|
|
1727
|
-
*/
|
|
1728
1459
|
readonly retryAfter?: number;
|
|
1729
|
-
/**
|
|
1730
|
-
* `safeToRetry` as reported by the server body. Prefer this over the
|
|
1731
|
-
* code-based heuristic when available — the server knows more about
|
|
1732
|
-
* whether the same request will succeed on retry.
|
|
1733
|
-
*/
|
|
1734
1460
|
private readonly serverSafeToRetry?;
|
|
1735
1461
|
constructor(code: PafiBackendErrorCode, message: string, httpStatus: number, details?: unknown | undefined, opts?: {
|
|
1736
1462
|
retryAfter?: number;
|
|
1737
1463
|
safeToRetry?: boolean;
|
|
1738
1464
|
});
|
|
1739
|
-
/**
|
|
1740
|
-
* Whether the caller can safely retry the same request.
|
|
1741
|
-
*
|
|
1742
|
-
* If the server provided `safeToRetry` in the body, trust that.
|
|
1743
|
-
* Otherwise fall back to a code-based heuristic.
|
|
1744
|
-
*/
|
|
1745
1465
|
get safeToRetry(): boolean;
|
|
1746
1466
|
}
|
|
1747
1467
|
|
|
1748
1468
|
/**
|
|
1749
|
-
*
|
|
1750
|
-
* [SPONSORED_PATH_FLOW.md] for the full flow + API contract.
|
|
1469
|
+
* Top-level configuration for `createIssuerService`.
|
|
1751
1470
|
*
|
|
1752
|
-
*
|
|
1753
|
-
*
|
|
1754
|
-
*
|
|
1755
|
-
|
|
1756
|
-
declare class PafiBackendClient {
|
|
1757
|
-
private readonly url;
|
|
1758
|
-
private readonly issuerId;
|
|
1759
|
-
private readonly apiKey;
|
|
1760
|
-
private readonly fetchImpl;
|
|
1761
|
-
private readonly timeoutMs;
|
|
1762
|
-
private readonly retry;
|
|
1763
|
-
constructor(config: PafiBackendConfig);
|
|
1764
|
-
/**
|
|
1765
|
-
* Request paymaster sponsorship for a pre-built UserOperation.
|
|
1766
|
-
* See [SPONSORED_PATH_FLOW.md §4.1] for the API contract.
|
|
1767
|
-
*
|
|
1768
|
-
* Retries automatically on transient failures (5xx, timeouts, network
|
|
1769
|
-
* errors, and errors the server flags with `safeToRetry: true`) up to
|
|
1770
|
-
* `retry.maxAttempts`. 4xx errors that are not `safeToRetry` fail fast.
|
|
1771
|
-
*
|
|
1772
|
-
* @throws PafiBackendError on final failure after exhausting retries
|
|
1773
|
-
*/
|
|
1774
|
-
requestSponsorship(req: SponsorshipRequest): Promise<SponsorshipResponse>;
|
|
1775
|
-
private postWithRetry;
|
|
1776
|
-
/**
|
|
1777
|
-
* Pick the delay before the next retry.
|
|
1778
|
-
* - If the server sent `retryAfter` (seconds), honor it (capped by
|
|
1779
|
-
* `maxRetryAfterMs`) — returns null if the server wait exceeds the
|
|
1780
|
-
* cap, signalling the caller should give up.
|
|
1781
|
-
* - Otherwise: exponential backoff with ±20% jitter, capped at
|
|
1782
|
-
* `maxDelayMs`.
|
|
1783
|
-
*/
|
|
1784
|
-
private computeBackoff;
|
|
1785
|
-
private sleep;
|
|
1786
|
-
private post;
|
|
1787
|
-
/** JSON replacer that stringifies bigints. Paired with bigintReviver. */
|
|
1788
|
-
private bigintReplacer;
|
|
1789
|
-
/**
|
|
1790
|
-
* JSON reviver that coerces specific numeric-string fields back to
|
|
1791
|
-
* bigint. The server must send these fields as decimal strings.
|
|
1792
|
-
*/
|
|
1793
|
-
private bigintReviver;
|
|
1794
|
-
}
|
|
1795
|
-
|
|
1796
|
-
/**
|
|
1797
|
-
* Top-level configuration for `createIssuerService`. Everything except
|
|
1798
|
-
* the chain metadata, wallets, auth secret, and `signer` is optional and
|
|
1799
|
-
* falls back to the in-memory dev defaults — that makes the happy path
|
|
1800
|
-
* a single-call wire-up while still letting production issuers plug in
|
|
1801
|
-
* their own ledger, session store, policy engine, and KMS signer.
|
|
1471
|
+
* In v1.4 the SDK is HTTP-client-free: it signs EIP-712 messages, reads
|
|
1472
|
+
* on-chain state, builds unsigned UserOperations, and maintains the
|
|
1473
|
+
* off-chain ledger. It never broadcasts transactions — that's the
|
|
1474
|
+
* frontend's responsibility via Bundler + Paymaster.
|
|
1802
1475
|
*
|
|
1803
|
-
* **Multi-token (0.2.0):** Pass `pointTokenAddresses: Address[]` to
|
|
1476
|
+
* **Multi-token (0.2.0+):** Pass `pointTokenAddresses: Address[]` to
|
|
1804
1477
|
* support multiple PointTokens under a single issuer backend. Legacy
|
|
1805
1478
|
* `pointTokenAddress: Address` still works for single-token deployments.
|
|
1806
1479
|
* When both are provided, `pointTokenAddresses` takes precedence.
|
|
1807
1480
|
*/
|
|
1808
1481
|
interface IssuerServiceConfig {
|
|
1809
1482
|
chainId: number;
|
|
1810
|
-
/**
|
|
1811
|
-
* Address of the deployed PointToken. Legacy single-token shortcut;
|
|
1812
|
-
* prefer `pointTokenAddresses` for multi-token issuers.
|
|
1813
|
-
*/
|
|
1483
|
+
/** Legacy single-token shortcut; prefer `pointTokenAddresses`. */
|
|
1814
1484
|
pointTokenAddress?: Address;
|
|
1815
|
-
/**
|
|
1816
|
-
* All PointToken addresses this issuer supports. Takes precedence over
|
|
1817
|
-
* `pointTokenAddress`. Factory creates one `PointIndexer` per address.
|
|
1818
|
-
*/
|
|
1485
|
+
/** All PointToken addresses this issuer supports. */
|
|
1819
1486
|
pointTokenAddresses?: Address[];
|
|
1820
|
-
/** Address of the deployed Relay contract. */
|
|
1821
|
-
relayAddress: Address;
|
|
1822
1487
|
/**
|
|
1823
1488
|
* Full contract address bundle returned verbatim by `handleConfig` so
|
|
1824
1489
|
* the frontend SDK can pick them up.
|
|
@@ -1829,8 +1494,6 @@ interface IssuerServiceConfig {
|
|
|
1829
1494
|
* polling, and gas-price lookups. Must be pointed at the target chain.
|
|
1830
1495
|
*/
|
|
1831
1496
|
provider: PublicClient;
|
|
1832
|
-
/** Operator wallet — pays gas, receives the operator fee. */
|
|
1833
|
-
operatorWallet: OperatorWalletLike;
|
|
1834
1497
|
auth: {
|
|
1835
1498
|
jwtSecret: string;
|
|
1836
1499
|
/** SIWE-style login-message domain, e.g. `"app.example.com"`. */
|
|
@@ -1838,19 +1501,12 @@ interface IssuerServiceConfig {
|
|
|
1838
1501
|
/** Passed straight to `jose` (`"24h"`, `"7d"`, …). Default `"24h"`. */
|
|
1839
1502
|
jwtExpiresIn?: string;
|
|
1840
1503
|
};
|
|
1841
|
-
/**
|
|
1842
|
-
* Issuer signer. No default — production issuers MUST plug in an
|
|
1843
|
-
* HSM/KMS-backed implementation. For local development use
|
|
1844
|
-
* `PrivateKeySigner` directly.
|
|
1845
|
-
*/
|
|
1846
|
-
signer: IIssuerSigner;
|
|
1847
1504
|
ledger?: IPointLedger;
|
|
1848
1505
|
policy?: IPolicyEngine;
|
|
1849
1506
|
sessionStore?: ISessionStore;
|
|
1850
1507
|
/**
|
|
1851
1508
|
* Fee management config. If omitted the `handleGasFee` endpoint will
|
|
1852
|
-
* throw "not configured" at request time.
|
|
1853
|
-
* to opt in — `provider` is inherited from the outer config.
|
|
1509
|
+
* throw "not configured" at request time.
|
|
1854
1510
|
*/
|
|
1855
1511
|
fee?: Omit<FeeManagerConfig, "provider">;
|
|
1856
1512
|
/**
|
|
@@ -1870,32 +1526,18 @@ interface IssuerServiceConfig {
|
|
|
1870
1526
|
*/
|
|
1871
1527
|
autoStart?: boolean;
|
|
1872
1528
|
};
|
|
1873
|
-
relay?: {
|
|
1874
|
-
simulateBeforeSubmit?: boolean;
|
|
1875
|
-
confirmationTimeoutMs?: number;
|
|
1876
|
-
};
|
|
1877
|
-
gateway?: {
|
|
1878
|
-
/** Extra lock TTL buffer beyond consent deadline. Default 60_000 ms. */
|
|
1879
|
-
defaultLockBufferMs?: number;
|
|
1880
|
-
};
|
|
1881
1529
|
}
|
|
1882
1530
|
interface IssuerService {
|
|
1883
1531
|
authService: AuthService;
|
|
1884
1532
|
sessionStore: ISessionStore;
|
|
1885
1533
|
ledger: IPointLedger;
|
|
1886
1534
|
policy: IPolicyEngine;
|
|
1887
|
-
signer: IIssuerSigner;
|
|
1888
1535
|
relayService: RelayService;
|
|
1889
1536
|
feeManager: FeeManager | undefined;
|
|
1890
|
-
|
|
1891
|
-
/**
|
|
1892
|
-
* All indexers keyed by PointToken address. For multi-token issuers there
|
|
1893
|
-
* is one per configured token. Single-token issuers will find one entry.
|
|
1894
|
-
*/
|
|
1537
|
+
/** All indexers keyed by PointToken address. */
|
|
1895
1538
|
indexers: Map<Address, PointIndexer>;
|
|
1896
1539
|
/**
|
|
1897
|
-
* First indexer. Kept for backward compat with 0.1.x callers
|
|
1898
|
-
* expected `service.indexer` to be a single instance.
|
|
1540
|
+
* First indexer. Kept for backward compat with 0.1.x callers.
|
|
1899
1541
|
* @deprecated use `indexers.get(tokenAddress)` for multi-token.
|
|
1900
1542
|
*/
|
|
1901
1543
|
indexer: PointIndexer;
|
|
@@ -1903,8 +1545,6 @@ interface IssuerService {
|
|
|
1903
1545
|
}
|
|
1904
1546
|
/**
|
|
1905
1547
|
* Wire a fully-functional issuer service from a single config object.
|
|
1906
|
-
* Returns every constructed collaborator so the caller can also use the
|
|
1907
|
-
* indexer or relay service directly outside the HTTP layer.
|
|
1908
1548
|
*
|
|
1909
1549
|
* Defaults:
|
|
1910
1550
|
* - `ledger` → `MemoryPointLedger`
|
|
@@ -1914,12 +1554,11 @@ interface IssuerService {
|
|
|
1914
1554
|
* - `poolsProvider` → undefined (handlePools throws until configured)
|
|
1915
1555
|
* - `indexer.autoStart` → false
|
|
1916
1556
|
*
|
|
1917
|
-
* Throws synchronously if any required field
|
|
1918
|
-
* `operatorWallet`, `auth.jwtSecret`, at least one point token) is missing.
|
|
1557
|
+
* Throws synchronously if any required field is missing.
|
|
1919
1558
|
*/
|
|
1920
1559
|
declare function createIssuerService(config: IssuerServiceConfig): IssuerService;
|
|
1921
1560
|
|
|
1922
1561
|
/** SDK package version — bumped on every release */
|
|
1923
1562
|
declare const PAFI_ISSUER_SDK_VERSION = "0.1.0";
|
|
1924
1563
|
|
|
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
|
|
1564
|
+
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 MintEvent, type MintingStatus, NonceManager, PAFI_ISSUER_SDK_VERSION, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, type PrepareBurnDirectParams, type PrepareBurnParams, type PrepareBurnWithSigParams, type PrepareMintParams, PrivateKeySigner, type PrivateKeySignerOptions, RelayError, type RelayErrorCode, RelayService, type RetryConfig, type Session, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, TopUpRedemptionError, TopUpRedemptionHandler, type TopUpRedemptionHandlerConfig, type TopUpRedemptionRequest, type TopUpRedemptionResponse, authenticateRequest, createIssuerService, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider };
|