@pafi-dev/issuer 0.3.0-beta.7 → 0.3.0-beta.8

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, WalletClient } from 'viem';
2
- import { PointTokenDomainConfig, MintRequest, EIP712Signature, PartialUserOperation, BurnRequest, ReceiverConsent, PathKey, PoolKey, SponsorshipScenario } from '@pafi-dev/core';
2
+ import { PointTokenDomainConfig, MintRequest, EIP712Signature, PartialUserOperation, BurnRequest, ReceiverConsent, PathKey, PoolKey, SponsorAuthScenario, SponsorAuthPayload, SponsorshipScenario } from '@pafi-dev/core';
3
3
 
4
4
  /**
5
5
  * Lifecycle of a minting request as tracked by the issuer's point ledger.
@@ -1486,35 +1486,83 @@ interface PafiBackendConfig {
1486
1486
  */
1487
1487
  retry?: RetryConfig;
1488
1488
  }
1489
- /** Paired with `POST /paymaster/sponsor`. See SPONSORED_PATH_FLOW.md §4.1 */
1489
+ /**
1490
+ * @deprecated Coinbase paymaster path — replaced by SponsorAuth in beta.8.
1491
+ * Kept for back-compat with consumers still on Coinbase. Will be removed
1492
+ * in 1.0.
1493
+ */
1490
1494
  interface SponsorshipRequest {
1491
1495
  chainId: number;
1492
1496
  scenario: SponsorshipScenario;
1493
1497
  userOp: PartialUserOperation;
1494
1498
  target: {
1495
- /** The allowlisted contract this batch call targets. */
1496
1499
  contract: Address;
1497
- /** Function selector / name — validated against allowlist. */
1498
1500
  function: string;
1499
- /** The PointToken involved (for scenario context). */
1500
1501
  pointToken?: Address;
1501
1502
  };
1502
1503
  }
1504
+ /** @deprecated See `SponsorshipRequest`. Use `SponsorAuthResponse` in beta.8+. */
1503
1505
  interface SponsorshipResponse {
1504
1506
  paymaster: Address;
1505
1507
  paymasterData: Hex;
1506
1508
  paymasterVerificationGasLimit: bigint;
1507
1509
  paymasterPostOpGasLimit: bigint;
1508
- /** Unix seconds when this sponsorship expires. Re-request after. */
1509
1510
  expiresAt: number;
1510
1511
  }
1512
+
1513
+ /**
1514
+ * Request body for `POST /sponsor-auth` against PAFI sponsor-relayer.
1515
+ * See `pafi-backend/docs/SPONSOR_AUTH_DESIGN.md` for the full spec.
1516
+ *
1517
+ * The endpoint:
1518
+ * 1. Authenticates user (JWT) + issuer (API key)
1519
+ * 2. Per-(user, scenario) rate-limits
1520
+ * 3. Per-issuer daily budget check
1521
+ * 4. Scenario-specific intent validation (mint cap, KYC, etc.)
1522
+ * 5. Allocates a unique nonce
1523
+ * 6. Signs the SponsorAuth payload via KMS-backed PAFI key
1524
+ * 7. Returns `{ sponsorAuth, payload }` for FE to forward to Privy
1525
+ */
1526
+ interface SponsorAuthRequest {
1527
+ chainId: number;
1528
+ scenario: SponsorAuthScenario;
1529
+ /** The exact UserOp the FE intends to submit. callDataHash binds to this. */
1530
+ userOp: PartialUserOperation;
1531
+ /** Issuer ID this sponsorship is billed against (e.g. "gg56"). */
1532
+ issuerId: string;
1533
+ /**
1534
+ * Scenario-specific context for intent validation. The relayer reads
1535
+ * these to apply scenario rules — e.g. preValidateMint reads
1536
+ * pointToken + amount to check the issuer cap.
1537
+ */
1538
+ context?: {
1539
+ pointToken?: Address;
1540
+ /** Decimal string representation (handles bigint over JSON). */
1541
+ amount?: string;
1542
+ brokerHash?: Hex;
1543
+ };
1544
+ }
1511
1545
  /**
1512
- * Machine-readable error codes returned by PAFI Backend.
1546
+ * Response from `POST /sponsor-auth`.
1513
1547
  *
1514
- * Source of truth: `apps/paymaster-proxy` `CalldataValidationError`,
1515
- * `RateLimitError`, `CoinbaseClientError`. Keep in sync.
1548
+ * `payload` is returned alongside `sponsorAuth` so the FE doesn't have
1549
+ * to reconstruct the message — just forwards both to Privy. Privy
1550
+ * verifier checks `signature` recovers to PAFI's registered pubkey
1551
+ * over `payload`.
1516
1552
  */
1517
- 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";
1553
+ interface SponsorAuthResponse {
1554
+ /** EIP-712 signature, hex-encoded 65 bytes. */
1555
+ sponsorAuth: Hex;
1556
+ /** The payload that was signed. Pass to Privy alongside the signature. */
1557
+ payload: SponsorAuthPayload;
1558
+ }
1559
+ /**
1560
+ * Machine-readable error codes returned by PAFI sponsor-relayer.
1561
+ *
1562
+ * Source of truth: `apps/sponsor-relayer/src/**` (renamed from
1563
+ * paymaster-proxy in beta.8). Keep in sync.
1564
+ */
1565
+ 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" | "KMS_UNAVAILABLE" | "SPONSOR_AUTH_SIGNING_FAILED" | "PAYMASTER_REJECTED" | "PAYMASTER_UNAVAILABLE" | "PAYMASTER_TIMEOUT" | "CALLDATA_INVALID" | "CALLDATA_EMPTY_BATCH" | "TARGET_NOT_ALLOWLISTED" | "FUNCTION_NOT_ALLOWED" | "SCENARIO_MISMATCH" | "SCENARIO_DISABLED" | "BAD_REQUEST" | "INTERNAL_ERROR" | "TIMEOUT" | "NETWORK_ERROR";
1518
1566
  declare class PafiBackendError extends Error {
1519
1567
  code: PafiBackendErrorCode;
1520
1568
  httpStatus: number;
@@ -1560,15 +1608,31 @@ declare class PafiBackendClient {
1560
1608
  private readonly retry;
1561
1609
  constructor(config: PafiBackendConfig);
1562
1610
  /**
1563
- * Request paymaster sponsorship for a pre-built UserOperation.
1564
- * See [SPONSORED_PATH_FLOW.md §4.1] for the API contract.
1611
+ * Request a SponsorAuth signature from PAFI sponsor-relayer (beta.8+).
1612
+ *
1613
+ * The relayer:
1614
+ * 1. Authenticates user (JWT) + issuer (API key)
1615
+ * 2. Per-(user, scenario) rate limit + per-issuer daily budget
1616
+ * 3. Scenario-specific intent validation (mint cap, KYC, etc.)
1617
+ * 4. Allocates nonce + signs SponsorAuth payload via KMS PAFI key
1618
+ * 5. Returns `{ sponsorAuth, payload }` for the FE to forward to
1619
+ * Privy's `signUserOperation({ sponsorAuth, payload })`.
1620
+ *
1621
+ * Retries on transient failures (5xx, timeouts, KMS unavailable,
1622
+ * rate-limit-with-retryAfter). 4xx that are not `safeToRetry` fail fast.
1565
1623
  *
1566
- * Retries automatically on transient failures (5xx, timeouts, network
1567
- * errors, and errors the server flags with `safeToRetry: true`) up to
1568
- * `retry.maxAttempts`. 4xx errors that are not `safeToRetry` fail fast.
1624
+ * See `pafi-backend/docs/SPONSOR_AUTH_DESIGN.md` for the full spec.
1569
1625
  *
1570
1626
  * @throws PafiBackendError on final failure after exhausting retries
1571
1627
  */
1628
+ requestSponsorAuth(req: SponsorAuthRequest): Promise<SponsorAuthResponse>;
1629
+ /**
1630
+ * @deprecated Coinbase paymaster path — replaced by `requestSponsorAuth`
1631
+ * in beta.8. Will be removed in 1.0. Migrate by:
1632
+ * 1. Switch to `requestSponsorAuth` returning `{ sponsorAuth, payload }`
1633
+ * 2. Pass both to Privy `signUserOperation` instead of merging
1634
+ * paymasterData into the UserOp callData
1635
+ */
1572
1636
  requestSponsorship(req: SponsorshipRequest): Promise<SponsorshipResponse>;
1573
1637
  private postWithRetry;
1574
1638
  /**
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Address, Hex, PublicClient, Chain, WalletClient } from 'viem';
2
- import { PointTokenDomainConfig, MintRequest, EIP712Signature, PartialUserOperation, BurnRequest, ReceiverConsent, PathKey, PoolKey, SponsorshipScenario } from '@pafi-dev/core';
2
+ import { PointTokenDomainConfig, MintRequest, EIP712Signature, PartialUserOperation, BurnRequest, ReceiverConsent, PathKey, PoolKey, SponsorAuthScenario, SponsorAuthPayload, SponsorshipScenario } from '@pafi-dev/core';
3
3
 
4
4
  /**
5
5
  * Lifecycle of a minting request as tracked by the issuer's point ledger.
@@ -1486,35 +1486,83 @@ interface PafiBackendConfig {
1486
1486
  */
1487
1487
  retry?: RetryConfig;
1488
1488
  }
1489
- /** Paired with `POST /paymaster/sponsor`. See SPONSORED_PATH_FLOW.md §4.1 */
1489
+ /**
1490
+ * @deprecated Coinbase paymaster path — replaced by SponsorAuth in beta.8.
1491
+ * Kept for back-compat with consumers still on Coinbase. Will be removed
1492
+ * in 1.0.
1493
+ */
1490
1494
  interface SponsorshipRequest {
1491
1495
  chainId: number;
1492
1496
  scenario: SponsorshipScenario;
1493
1497
  userOp: PartialUserOperation;
1494
1498
  target: {
1495
- /** The allowlisted contract this batch call targets. */
1496
1499
  contract: Address;
1497
- /** Function selector / name — validated against allowlist. */
1498
1500
  function: string;
1499
- /** The PointToken involved (for scenario context). */
1500
1501
  pointToken?: Address;
1501
1502
  };
1502
1503
  }
1504
+ /** @deprecated See `SponsorshipRequest`. Use `SponsorAuthResponse` in beta.8+. */
1503
1505
  interface SponsorshipResponse {
1504
1506
  paymaster: Address;
1505
1507
  paymasterData: Hex;
1506
1508
  paymasterVerificationGasLimit: bigint;
1507
1509
  paymasterPostOpGasLimit: bigint;
1508
- /** Unix seconds when this sponsorship expires. Re-request after. */
1509
1510
  expiresAt: number;
1510
1511
  }
1512
+
1513
+ /**
1514
+ * Request body for `POST /sponsor-auth` against PAFI sponsor-relayer.
1515
+ * See `pafi-backend/docs/SPONSOR_AUTH_DESIGN.md` for the full spec.
1516
+ *
1517
+ * The endpoint:
1518
+ * 1. Authenticates user (JWT) + issuer (API key)
1519
+ * 2. Per-(user, scenario) rate-limits
1520
+ * 3. Per-issuer daily budget check
1521
+ * 4. Scenario-specific intent validation (mint cap, KYC, etc.)
1522
+ * 5. Allocates a unique nonce
1523
+ * 6. Signs the SponsorAuth payload via KMS-backed PAFI key
1524
+ * 7. Returns `{ sponsorAuth, payload }` for FE to forward to Privy
1525
+ */
1526
+ interface SponsorAuthRequest {
1527
+ chainId: number;
1528
+ scenario: SponsorAuthScenario;
1529
+ /** The exact UserOp the FE intends to submit. callDataHash binds to this. */
1530
+ userOp: PartialUserOperation;
1531
+ /** Issuer ID this sponsorship is billed against (e.g. "gg56"). */
1532
+ issuerId: string;
1533
+ /**
1534
+ * Scenario-specific context for intent validation. The relayer reads
1535
+ * these to apply scenario rules — e.g. preValidateMint reads
1536
+ * pointToken + amount to check the issuer cap.
1537
+ */
1538
+ context?: {
1539
+ pointToken?: Address;
1540
+ /** Decimal string representation (handles bigint over JSON). */
1541
+ amount?: string;
1542
+ brokerHash?: Hex;
1543
+ };
1544
+ }
1511
1545
  /**
1512
- * Machine-readable error codes returned by PAFI Backend.
1546
+ * Response from `POST /sponsor-auth`.
1513
1547
  *
1514
- * Source of truth: `apps/paymaster-proxy` `CalldataValidationError`,
1515
- * `RateLimitError`, `CoinbaseClientError`. Keep in sync.
1548
+ * `payload` is returned alongside `sponsorAuth` so the FE doesn't have
1549
+ * to reconstruct the message — just forwards both to Privy. Privy
1550
+ * verifier checks `signature` recovers to PAFI's registered pubkey
1551
+ * over `payload`.
1516
1552
  */
1517
- 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";
1553
+ interface SponsorAuthResponse {
1554
+ /** EIP-712 signature, hex-encoded 65 bytes. */
1555
+ sponsorAuth: Hex;
1556
+ /** The payload that was signed. Pass to Privy alongside the signature. */
1557
+ payload: SponsorAuthPayload;
1558
+ }
1559
+ /**
1560
+ * Machine-readable error codes returned by PAFI sponsor-relayer.
1561
+ *
1562
+ * Source of truth: `apps/sponsor-relayer/src/**` (renamed from
1563
+ * paymaster-proxy in beta.8). Keep in sync.
1564
+ */
1565
+ 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" | "KMS_UNAVAILABLE" | "SPONSOR_AUTH_SIGNING_FAILED" | "PAYMASTER_REJECTED" | "PAYMASTER_UNAVAILABLE" | "PAYMASTER_TIMEOUT" | "CALLDATA_INVALID" | "CALLDATA_EMPTY_BATCH" | "TARGET_NOT_ALLOWLISTED" | "FUNCTION_NOT_ALLOWED" | "SCENARIO_MISMATCH" | "SCENARIO_DISABLED" | "BAD_REQUEST" | "INTERNAL_ERROR" | "TIMEOUT" | "NETWORK_ERROR";
1518
1566
  declare class PafiBackendError extends Error {
1519
1567
  code: PafiBackendErrorCode;
1520
1568
  httpStatus: number;
@@ -1560,15 +1608,31 @@ declare class PafiBackendClient {
1560
1608
  private readonly retry;
1561
1609
  constructor(config: PafiBackendConfig);
1562
1610
  /**
1563
- * Request paymaster sponsorship for a pre-built UserOperation.
1564
- * See [SPONSORED_PATH_FLOW.md §4.1] for the API contract.
1611
+ * Request a SponsorAuth signature from PAFI sponsor-relayer (beta.8+).
1612
+ *
1613
+ * The relayer:
1614
+ * 1. Authenticates user (JWT) + issuer (API key)
1615
+ * 2. Per-(user, scenario) rate limit + per-issuer daily budget
1616
+ * 3. Scenario-specific intent validation (mint cap, KYC, etc.)
1617
+ * 4. Allocates nonce + signs SponsorAuth payload via KMS PAFI key
1618
+ * 5. Returns `{ sponsorAuth, payload }` for the FE to forward to
1619
+ * Privy's `signUserOperation({ sponsorAuth, payload })`.
1620
+ *
1621
+ * Retries on transient failures (5xx, timeouts, KMS unavailable,
1622
+ * rate-limit-with-retryAfter). 4xx that are not `safeToRetry` fail fast.
1565
1623
  *
1566
- * Retries automatically on transient failures (5xx, timeouts, network
1567
- * errors, and errors the server flags with `safeToRetry: true`) up to
1568
- * `retry.maxAttempts`. 4xx errors that are not `safeToRetry` fail fast.
1624
+ * See `pafi-backend/docs/SPONSOR_AUTH_DESIGN.md` for the full spec.
1569
1625
  *
1570
1626
  * @throws PafiBackendError on final failure after exhausting retries
1571
1627
  */
1628
+ requestSponsorAuth(req: SponsorAuthRequest): Promise<SponsorAuthResponse>;
1629
+ /**
1630
+ * @deprecated Coinbase paymaster path — replaced by `requestSponsorAuth`
1631
+ * in beta.8. Will be removed in 1.0. Migrate by:
1632
+ * 1. Switch to `requestSponsorAuth` returning `{ sponsorAuth, payload }`
1633
+ * 2. Pass both to Privy `signUserOperation` instead of merging
1634
+ * paymasterData into the UserOp callData
1635
+ */
1572
1636
  requestSponsorship(req: SponsorshipRequest): Promise<SponsorshipResponse>;
1573
1637
  private postWithRetry;
1574
1638
  /**
package/dist/index.js CHANGED
@@ -1827,18 +1827,22 @@ var PafiBackendError = class extends Error {
1827
1827
  get safeToRetry() {
1828
1828
  if (this.serverSafeToRetry !== void 0) return this.serverSafeToRetry;
1829
1829
  switch (this.code) {
1830
+ // Transient infra
1830
1831
  case "PAYMASTER_UNAVAILABLE":
1831
1832
  case "PAYMASTER_TIMEOUT":
1832
1833
  case "RATE_LIMITER_UNAVAILABLE":
1834
+ case "KMS_UNAVAILABLE":
1835
+ case "SPONSOR_AUTH_SIGNING_FAILED":
1833
1836
  case "INTERNAL_ERROR":
1834
1837
  case "TIMEOUT":
1835
1838
  case "NETWORK_ERROR":
1836
1839
  return true;
1840
+ // Rate-limited — safe to retry after retryAfter window
1837
1841
  case "RATE_LIMIT_EXCEEDED":
1838
1842
  case "RATE_LIMIT_EXCEEDED_DAILY":
1839
1843
  case "RATE_LIMIT_EXCEEDED_PER_USER":
1844
+ case "ISSUER_BUDGET_EXCEEDED":
1840
1845
  return true;
1841
- // after retryAfter
1842
1846
  default:
1843
1847
  return false;
1844
1848
  }
@@ -1886,15 +1890,36 @@ var PafiBackendClient = class {
1886
1890
  }
1887
1891
  }
1888
1892
  /**
1889
- * Request paymaster sponsorship for a pre-built UserOperation.
1890
- * See [SPONSORED_PATH_FLOW.md §4.1] for the API contract.
1893
+ * Request a SponsorAuth signature from PAFI sponsor-relayer (beta.8+).
1891
1894
  *
1892
- * Retries automatically on transient failures (5xx, timeouts, network
1893
- * errors, and errors the server flags with `safeToRetry: true`) up to
1894
- * `retry.maxAttempts`. 4xx errors that are not `safeToRetry` fail fast.
1895
+ * The relayer:
1896
+ * 1. Authenticates user (JWT) + issuer (API key)
1897
+ * 2. Per-(user, scenario) rate limit + per-issuer daily budget
1898
+ * 3. Scenario-specific intent validation (mint cap, KYC, etc.)
1899
+ * 4. Allocates nonce + signs SponsorAuth payload via KMS PAFI key
1900
+ * 5. Returns `{ sponsorAuth, payload }` for the FE to forward to
1901
+ * Privy's `signUserOperation({ sponsorAuth, payload })`.
1902
+ *
1903
+ * Retries on transient failures (5xx, timeouts, KMS unavailable,
1904
+ * rate-limit-with-retryAfter). 4xx that are not `safeToRetry` fail fast.
1905
+ *
1906
+ * See `pafi-backend/docs/SPONSOR_AUTH_DESIGN.md` for the full spec.
1895
1907
  *
1896
1908
  * @throws PafiBackendError on final failure after exhausting retries
1897
1909
  */
1910
+ async requestSponsorAuth(req) {
1911
+ return this.postWithRetry(
1912
+ "/sponsor-auth",
1913
+ req
1914
+ );
1915
+ }
1916
+ /**
1917
+ * @deprecated Coinbase paymaster path — replaced by `requestSponsorAuth`
1918
+ * in beta.8. Will be removed in 1.0. Migrate by:
1919
+ * 1. Switch to `requestSponsorAuth` returning `{ sponsorAuth, payload }`
1920
+ * 2. Pass both to Privy `signUserOperation` instead of merging
1921
+ * paymasterData into the UserOp callData
1922
+ */
1898
1923
  async requestSponsorship(req) {
1899
1924
  return this.postWithRetry(
1900
1925
  "/paymaster/sponsor",