@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.cjs CHANGED
@@ -34,12 +34,16 @@ __export(index_exports, {
34
34
  MintingGatewayError: () => MintingGatewayError,
35
35
  NonceManager: () => NonceManager,
36
36
  PAFI_ISSUER_SDK_VERSION: () => PAFI_ISSUER_SDK_VERSION,
37
+ PTRedeemError: () => PTRedeemError,
38
+ PTRedeemHandler: () => PTRedeemHandler,
37
39
  PafiBackendClient: () => PafiBackendClient,
38
40
  PafiBackendError: () => PafiBackendError,
39
41
  PointIndexer: () => PointIndexer,
40
42
  PrivateKeySigner: () => PrivateKeySigner,
41
43
  RelayError: () => RelayError,
42
44
  RelayService: () => RelayService,
45
+ TopUpRedemptionError: () => TopUpRedemptionError,
46
+ TopUpRedemptionHandler: () => TopUpRedemptionHandler,
43
47
  authenticateRequest: () => authenticateRequest,
44
48
  createIssuerService: () => createIssuerService,
45
49
  createSubgraphNativeUsdtQuoter: () => createSubgraphNativeUsdtQuoter,
@@ -630,6 +634,7 @@ var RelayError = class extends Error {
630
634
  };
631
635
 
632
636
  // src/relay/relayService.ts
637
+ var import_viem5 = require("viem");
633
638
  var import_core3 = require("@pafi-dev/core");
634
639
  var DEFAULT_CONFIRMATION_TIMEOUT_MS = 6e4;
635
640
  var RelayService = class {
@@ -755,6 +760,154 @@ var RelayService = class {
755
760
  );
756
761
  }
757
762
  }
763
+ // ==========================================================================
764
+ // v1.4 — Sponsored UserOp preparation (beta with mocked SC contracts)
765
+ // ==========================================================================
766
+ //
767
+ // These two methods build unsigned `PartialUserOperation` payloads for
768
+ // the Frontend to sign (via Privy) and submit to the Bundler. The
769
+ // Issuer Backend no longer broadcasts — that's the Frontend's job.
770
+ //
771
+ // Uses mocked Relayer v2 + PointToken ABIs from `@pafi-dev/core/contracts`.
772
+ // When SC delivers real ABIs, the imports swap but these method bodies
773
+ // stay the same (calldata encoder is ABI-driven).
774
+ // ==========================================================================
775
+ /**
776
+ * Build an unsigned UserOp for Scenario 1 (Mint).
777
+ *
778
+ * Flow:
779
+ * 1. Encode `Relayer.mint(request, userSig, issuerSig)` as the inner call
780
+ * 2. Optionally append a PT fee transfer from user → feeRecipient
781
+ * (fee recovery happens on-chain via BatchExecutor, not via an
782
+ * operator wallet)
783
+ * 3. Wrap all inner calls into `BatchExecutor.execute(calls[])`
784
+ * 4. Return a `PartialUserOperation` ready for:
785
+ * - gas estimation (Bundler)
786
+ * - paymaster sponsorship (PAFI Backend)
787
+ * - user signature (Privy)
788
+ */
789
+ prepareMint(params) {
790
+ if (!params.relayerAddress) {
791
+ throw new RelayError("ENCODE_FAILED", "prepareMint: relayerAddress required");
792
+ }
793
+ if (!params.batchExecutorAddress) {
794
+ throw new RelayError(
795
+ "ENCODE_FAILED",
796
+ "prepareMint: batchExecutorAddress required"
797
+ );
798
+ }
799
+ if (!params.userAddress) {
800
+ throw new RelayError("ENCODE_FAILED", "prepareMint: userAddress required");
801
+ }
802
+ let mintCallData;
803
+ try {
804
+ mintCallData = (0, import_viem5.encodeFunctionData)({
805
+ abi: import_core3.RELAYER_V2_ABI,
806
+ functionName: "mint",
807
+ args: [params.mintRequest, params.userSignature, params.issuerSignature]
808
+ });
809
+ } catch (err) {
810
+ throw new RelayError(
811
+ "ENCODE_FAILED",
812
+ `prepareMint: failed to encode Relayer.mint: ${errorMessage(err)}`,
813
+ err
814
+ );
815
+ }
816
+ const operations = [
817
+ {
818
+ target: params.relayerAddress,
819
+ value: 0n,
820
+ data: mintCallData
821
+ }
822
+ ];
823
+ if (params.mintRequest.feeAmount > 0n) {
824
+ operations.push({
825
+ target: params.pointTokenAddress,
826
+ value: 0n,
827
+ data: (0, import_viem5.encodeFunctionData)({
828
+ abi: import_core3.POINT_TOKEN_V2_ABI,
829
+ functionName: "balanceOf",
830
+ // placeholder — real impl uses transfer
831
+ args: [params.mintRequest.feeRecipient]
832
+ })
833
+ });
834
+ }
835
+ return (0, import_core3.buildPartialUserOperation)({
836
+ sender: params.userAddress,
837
+ nonce: params.aaNonce,
838
+ operations,
839
+ gasLimits: {
840
+ callGasLimit: params.callGasLimit ?? 500000n,
841
+ verificationGasLimit: params.verificationGasLimit ?? 150000n,
842
+ preVerificationGas: params.preVerificationGas ?? 50000n
843
+ }
844
+ });
845
+ }
846
+ /**
847
+ * Build an unsigned UserOp for Scenario 2 (Burn/Redeem).
848
+ *
849
+ * Two modes:
850
+ * - `mode: 'burn'` — direct `PointToken.burn(amount)`; `msg.sender`
851
+ * via EIP-7702 delegation is the user, so no signature needed
852
+ * on-chain (the BurnConsent was already verified off-chain by
853
+ * the issuer backend before we got here)
854
+ * - `mode: 'burnWithSig'` — `PointToken.burnWithSig(consent, sig)`;
855
+ * used when the issuer hasn't verified the consent and the
856
+ * contract has to do it on-chain
857
+ */
858
+ prepareBurn(params) {
859
+ if (!params.pointTokenAddress) {
860
+ throw new RelayError("ENCODE_FAILED", "prepareBurn: pointTokenAddress required");
861
+ }
862
+ if (!params.batchExecutorAddress) {
863
+ throw new RelayError(
864
+ "ENCODE_FAILED",
865
+ "prepareBurn: batchExecutorAddress required"
866
+ );
867
+ }
868
+ let burnCallData;
869
+ try {
870
+ if (params.mode === "burnWithSig") {
871
+ if (!params.burnConsent || !params.consentSignature) {
872
+ throw new Error("burnWithSig requires burnConsent + consentSignature");
873
+ }
874
+ burnCallData = (0, import_viem5.encodeFunctionData)({
875
+ abi: import_core3.POINT_TOKEN_V2_ABI,
876
+ functionName: "burnWithSig",
877
+ args: [params.burnConsent, params.consentSignature]
878
+ });
879
+ } else {
880
+ burnCallData = (0, import_viem5.encodeFunctionData)({
881
+ abi: import_core3.POINT_TOKEN_V2_ABI,
882
+ functionName: "burn",
883
+ args: [params.amount]
884
+ });
885
+ }
886
+ } catch (err) {
887
+ throw new RelayError(
888
+ "ENCODE_FAILED",
889
+ `prepareBurn: failed to encode burn call: ${errorMessage(err)}`,
890
+ err
891
+ );
892
+ }
893
+ const operations = [
894
+ {
895
+ target: params.pointTokenAddress,
896
+ value: 0n,
897
+ data: burnCallData
898
+ }
899
+ ];
900
+ return (0, import_core3.buildPartialUserOperation)({
901
+ sender: params.userAddress,
902
+ nonce: params.aaNonce,
903
+ operations,
904
+ gasLimits: {
905
+ callGasLimit: params.callGasLimit ?? 300000n,
906
+ verificationGasLimit: params.verificationGasLimit ?? 150000n,
907
+ preVerificationGas: params.preVerificationGas ?? 50000n
908
+ }
909
+ });
910
+ }
758
911
  };
759
912
  function errorMessage(err) {
760
913
  return err instanceof Error ? err.message : String(err);
@@ -1055,8 +1208,8 @@ var InMemoryCursorStore = class {
1055
1208
  };
1056
1209
 
1057
1210
  // src/indexer/pointIndexer.ts
1058
- var import_viem5 = require("viem");
1059
- var TRANSFER_EVENT = (0, import_viem5.parseAbiItem)(
1211
+ var import_viem6 = require("viem");
1212
+ var TRANSFER_EVENT = (0, import_viem6.parseAbiItem)(
1060
1213
  "event Transfer(address indexed from, address indexed to, uint256 value)"
1061
1214
  );
1062
1215
  var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
@@ -1176,10 +1329,10 @@ var PointIndexer = class {
1176
1329
  for (const log of logs) {
1177
1330
  const args = log.args;
1178
1331
  if (!args.from || !args.to || args.value === void 0) continue;
1179
- if ((0, import_viem5.getAddress)(args.from) !== ZERO_ADDRESS) continue;
1332
+ if ((0, import_viem6.getAddress)(args.from) !== ZERO_ADDRESS) continue;
1180
1333
  if (log.blockNumber === null || log.transactionHash === null) continue;
1181
1334
  out.push({
1182
- to: (0, import_viem5.getAddress)(args.to),
1335
+ to: (0, import_viem6.getAddress)(args.to),
1183
1336
  amount: args.value,
1184
1337
  blockNumber: log.blockNumber,
1185
1338
  txHash: log.transactionHash,
@@ -1235,8 +1388,8 @@ function pickMatchingLock(locks, amount) {
1235
1388
  }
1236
1389
 
1237
1390
  // src/indexer/burnIndexer.ts
1238
- var import_viem6 = require("viem");
1239
- var TRANSFER_EVENT2 = (0, import_viem6.parseAbiItem)(
1391
+ var import_viem7 = require("viem");
1392
+ var TRANSFER_EVENT2 = (0, import_viem7.parseAbiItem)(
1240
1393
  "event Transfer(address indexed from, address indexed to, uint256 value)"
1241
1394
  );
1242
1395
  var ZERO_ADDRESS2 = "0x0000000000000000000000000000000000000000";
@@ -1355,10 +1508,10 @@ var BurnIndexer = class {
1355
1508
  for (const log of logs) {
1356
1509
  const args = log.args;
1357
1510
  if (!args.from || !args.to || args.value === void 0) continue;
1358
- if ((0, import_viem6.getAddress)(args.to) !== ZERO_ADDRESS2) continue;
1511
+ if ((0, import_viem7.getAddress)(args.to) !== ZERO_ADDRESS2) continue;
1359
1512
  if (log.blockNumber === null || log.transactionHash === null) continue;
1360
1513
  out.push({
1361
- from: (0, import_viem6.getAddress)(args.from),
1514
+ from: (0, import_viem7.getAddress)(args.from),
1362
1515
  amount: args.value,
1363
1516
  blockNumber: log.blockNumber,
1364
1517
  txHash: log.transactionHash,
@@ -1386,7 +1539,7 @@ var BurnIndexer = class {
1386
1539
  };
1387
1540
 
1388
1541
  // src/api/handlers.ts
1389
- var import_viem7 = require("viem");
1542
+ var import_viem8 = require("viem");
1390
1543
  var import_core5 = require("@pafi-dev/core");
1391
1544
  var IssuerApiHandlers = class {
1392
1545
  authService;
@@ -1418,7 +1571,7 @@ var IssuerApiHandlers = class {
1418
1571
  "IssuerApiHandlers: pointTokenAddress or pointTokenAddresses required"
1419
1572
  );
1420
1573
  }
1421
- const normalized = raw.map((a) => (0, import_viem7.getAddress)(a));
1574
+ const normalized = raw.map((a) => (0, import_viem8.getAddress)(a));
1422
1575
  this.supportedTokens = new Set(normalized);
1423
1576
  this.defaultToken = normalized[0];
1424
1577
  this.chainId = config.chainId;
@@ -1519,14 +1672,14 @@ var IssuerApiHandlers = class {
1519
1672
  `handleUser: unsupported chainId ${request.chainId}`
1520
1673
  );
1521
1674
  }
1522
- const normalizedAuthed = (0, import_viem7.getAddress)(userAddress);
1523
- const normalizedRequest = (0, import_viem7.getAddress)(request.userAddress);
1675
+ const normalizedAuthed = (0, import_viem8.getAddress)(userAddress);
1676
+ const normalizedRequest = (0, import_viem8.getAddress)(request.userAddress);
1524
1677
  if (normalizedAuthed !== normalizedRequest) {
1525
1678
  throw new Error(
1526
1679
  "handleUser: request userAddress must match authenticated user"
1527
1680
  );
1528
1681
  }
1529
- const pointToken = (0, import_viem7.getAddress)(request.pointTokenAddress);
1682
+ const pointToken = (0, import_viem8.getAddress)(request.pointTokenAddress);
1530
1683
  if (!this.supportedTokens.has(pointToken)) {
1531
1684
  throw new Error(
1532
1685
  `handleUser: unsupported pointToken ${pointToken}`
@@ -1569,7 +1722,7 @@ var IssuerApiHandlers = class {
1569
1722
  `handleBuildConsentTypedData: unsupported chainId ${request.chainId}`
1570
1723
  );
1571
1724
  }
1572
- const pointToken = (0, import_viem7.getAddress)(request.pointTokenAddress);
1725
+ const pointToken = (0, import_viem8.getAddress)(request.pointTokenAddress);
1573
1726
  if (!this.supportedTokens.has(pointToken)) {
1574
1727
  throw new Error(
1575
1728
  `handleBuildConsentTypedData: unsupported pointToken ${pointToken}`
@@ -1609,14 +1762,14 @@ var IssuerApiHandlers = class {
1609
1762
  `handleClaimAndSwap: unsupported chainId ${request.chainId}`
1610
1763
  );
1611
1764
  }
1612
- const pointToken = (0, import_viem7.getAddress)(request.pointTokenAddress);
1765
+ const pointToken = (0, import_viem8.getAddress)(request.pointTokenAddress);
1613
1766
  if (!this.supportedTokens.has(pointToken)) {
1614
1767
  throw new Error(
1615
1768
  `handleClaimAndSwap: unsupported pointToken ${pointToken}`
1616
1769
  );
1617
1770
  }
1618
1771
  const result = await this.gateway.processMintAndCashOut({
1619
- userAddress: (0, import_viem7.getAddress)(userAddress),
1772
+ userAddress: (0, import_viem8.getAddress)(userAddress),
1620
1773
  pointTokenAddress: pointToken,
1621
1774
  chainId: request.chainId,
1622
1775
  domain: request.domain,
@@ -1636,6 +1789,183 @@ var IssuerApiHandlers = class {
1636
1789
  }
1637
1790
  };
1638
1791
 
1792
+ // src/api/handlers/ptRedeemHandler.ts
1793
+ var import_viem9 = require("viem");
1794
+ var import_core6 = require("@pafi-dev/core");
1795
+ var DEFAULT_REDEEM_LOCK_MS = 15 * 60 * 1e3;
1796
+ var PTRedeemError = class extends Error {
1797
+ constructor(code, message) {
1798
+ super(message);
1799
+ this.code = code;
1800
+ this.name = "PTRedeemError";
1801
+ }
1802
+ code;
1803
+ };
1804
+ var PTRedeemHandler = class {
1805
+ ledger;
1806
+ relayService;
1807
+ pointTokenAddress;
1808
+ batchExecutorAddress;
1809
+ chainId;
1810
+ domain;
1811
+ redeemLockDurationMs;
1812
+ now;
1813
+ constructor(config) {
1814
+ if (!config.ledger.reservePendingCredit) {
1815
+ throw new PTRedeemError(
1816
+ "LEDGER_NOT_SUPPORTED",
1817
+ "PTRedeemHandler requires a ledger that implements reservePendingCredit() (v0.3.0+)"
1818
+ );
1819
+ }
1820
+ this.ledger = config.ledger;
1821
+ this.relayService = config.relayService;
1822
+ this.pointTokenAddress = (0, import_viem9.getAddress)(config.pointTokenAddress);
1823
+ this.batchExecutorAddress = (0, import_viem9.getAddress)(config.batchExecutorAddress);
1824
+ this.chainId = config.chainId;
1825
+ this.domain = config.domain;
1826
+ this.redeemLockDurationMs = config.redeemLockDurationMs ?? DEFAULT_REDEEM_LOCK_MS;
1827
+ this.now = config.now ?? (() => Date.now());
1828
+ }
1829
+ async handle(request) {
1830
+ if (request.amount <= 0n) {
1831
+ throw new PTRedeemError("INVALID_CONSENT", "redeem amount must be positive");
1832
+ }
1833
+ if (request.consent.amount !== request.amount) {
1834
+ throw new PTRedeemError(
1835
+ "AMOUNT_MISMATCH",
1836
+ `consent.amount (${request.consent.amount}) must match request.amount (${request.amount})`
1837
+ );
1838
+ }
1839
+ const nowSeconds = BigInt(Math.floor(this.now() / 1e3));
1840
+ if (request.consent.deadline <= nowSeconds) {
1841
+ throw new PTRedeemError(
1842
+ "EXPIRED_CONSENT",
1843
+ `consent deadline (${request.consent.deadline}) already passed`
1844
+ );
1845
+ }
1846
+ const verification = await (0, import_core6.verifyBurnConsent)(
1847
+ {
1848
+ name: this.domain.name,
1849
+ chainId: this.chainId,
1850
+ verifyingContract: this.domain.verifyingContract ?? this.pointTokenAddress
1851
+ },
1852
+ request.consent,
1853
+ request.consentSignature,
1854
+ request.userAddress
1855
+ );
1856
+ if (!verification.isValid) {
1857
+ throw new PTRedeemError(
1858
+ "SIGNATURE_MISMATCH",
1859
+ `signer mismatch \u2014 expected ${request.userAddress}, got ${verification.recoveredAddress}`
1860
+ );
1861
+ }
1862
+ const lockId = await this.ledger.reservePendingCredit(
1863
+ request.userAddress,
1864
+ request.amount,
1865
+ this.redeemLockDurationMs,
1866
+ this.pointTokenAddress
1867
+ );
1868
+ const userOp = this.relayService.prepareBurn({
1869
+ mode: "burnWithSig",
1870
+ userAddress: request.userAddress,
1871
+ aaNonce: request.aaNonce,
1872
+ pointTokenAddress: this.pointTokenAddress,
1873
+ batchExecutorAddress: this.batchExecutorAddress,
1874
+ burnConsent: request.consent,
1875
+ consentSignature: parseSigStruct(request.consentSignature)
1876
+ });
1877
+ return {
1878
+ lockId,
1879
+ userOp,
1880
+ expiresInSeconds: Math.floor(this.redeemLockDurationMs / 1e3)
1881
+ };
1882
+ }
1883
+ };
1884
+ function parseSigStruct(serialized) {
1885
+ const raw = serialized.slice(2);
1886
+ if (raw.length !== 130) {
1887
+ throw new PTRedeemError(
1888
+ "INVALID_CONSENT",
1889
+ `signature must be 65 bytes, got ${raw.length / 2}`
1890
+ );
1891
+ }
1892
+ const r = `0x${raw.slice(0, 64)}`;
1893
+ const s = `0x${raw.slice(64, 128)}`;
1894
+ const v = parseInt(raw.slice(128, 130), 16);
1895
+ return { v, r, s };
1896
+ }
1897
+
1898
+ // src/api/handlers/topUpRedemptionHandler.ts
1899
+ var import_viem10 = require("viem");
1900
+ var import_core7 = require("@pafi-dev/core");
1901
+ var TopUpRedemptionError = class extends Error {
1902
+ constructor(code, message) {
1903
+ super(message);
1904
+ this.code = code;
1905
+ this.name = "TopUpRedemptionError";
1906
+ }
1907
+ code;
1908
+ };
1909
+ var TopUpRedemptionHandler = class {
1910
+ ledger;
1911
+ ptRedeemHandler;
1912
+ provider;
1913
+ pointTokenAddress;
1914
+ constructor(config) {
1915
+ this.ledger = config.ledger;
1916
+ this.ptRedeemHandler = config.ptRedeemHandler;
1917
+ this.provider = config.provider;
1918
+ this.pointTokenAddress = (0, import_viem10.getAddress)(config.pointTokenAddress);
1919
+ }
1920
+ async handle(request) {
1921
+ const offChainBalance = await this.ledger.getBalance(
1922
+ request.userAddress,
1923
+ this.pointTokenAddress
1924
+ );
1925
+ if (offChainBalance >= request.requiredAmount) {
1926
+ return { action: "NO_TOP_UP_NEEDED", offChainBalance };
1927
+ }
1928
+ const shortfall = request.requiredAmount - offChainBalance;
1929
+ const onChainBalance = await (0, import_core7.getPointTokenBalance)(
1930
+ this.provider,
1931
+ this.pointTokenAddress,
1932
+ request.userAddress
1933
+ );
1934
+ if (onChainBalance < shortfall) {
1935
+ return {
1936
+ action: "INSUFFICIENT_ONCHAIN",
1937
+ offChainBalance,
1938
+ onChainBalance,
1939
+ shortfall
1940
+ };
1941
+ }
1942
+ if (request.redeemRequest.consent.amount < shortfall) {
1943
+ throw new TopUpRedemptionError(
1944
+ "CONSENT_AMOUNT_TOO_LOW",
1945
+ `consent.amount (${request.redeemRequest.consent.amount}) must cover shortfall (${shortfall})`
1946
+ );
1947
+ }
1948
+ if (request.redeemRequest.consent.amount !== shortfall) {
1949
+ throw new TopUpRedemptionError(
1950
+ "CONSENT_AMOUNT_TOO_LOW",
1951
+ `consent.amount (${request.redeemRequest.consent.amount}) must equal shortfall (${shortfall}) exactly \u2014 re-sign with correct amount`
1952
+ );
1953
+ }
1954
+ const redeem = await this.ptRedeemHandler.handle({
1955
+ userAddress: request.userAddress,
1956
+ amount: shortfall,
1957
+ consent: request.redeemRequest.consent,
1958
+ consentSignature: request.redeemRequest.consentSignature,
1959
+ aaNonce: request.redeemRequest.aaNonce
1960
+ });
1961
+ return {
1962
+ action: "TOP_UP_STARTED",
1963
+ shortfall,
1964
+ redeem
1965
+ };
1966
+ }
1967
+ };
1968
+
1639
1969
  // src/pools/subgraphPoolsProvider.ts
1640
1970
  var DEFAULT_CACHE_TTL_MS = 3e4;
1641
1971
  var POOL_QUERY = `
@@ -1848,7 +2178,7 @@ function toUsdtPerNative(priceFloat, usdtDecimals) {
1848
2178
  }
1849
2179
 
1850
2180
  // src/balance/balanceAggregator.ts
1851
- var import_core6 = require("@pafi-dev/core");
2181
+ var import_core8 = require("@pafi-dev/core");
1852
2182
  var BalanceAggregator = class {
1853
2183
  provider;
1854
2184
  ledger;
@@ -1869,7 +2199,7 @@ var BalanceAggregator = class {
1869
2199
  async getCombinedBalance(user, pointToken) {
1870
2200
  const [offChain, onChain] = await Promise.all([
1871
2201
  this.ledger.getBalance(user, pointToken),
1872
- (0, import_core6.getPointTokenBalance)(this.provider, pointToken, user)
2202
+ (0, import_core8.getPointTokenBalance)(this.provider, pointToken, user)
1873
2203
  ]);
1874
2204
  return {
1875
2205
  offChain,
@@ -2114,7 +2444,7 @@ var PafiBackendClient = class {
2114
2444
  };
2115
2445
 
2116
2446
  // src/config.ts
2117
- var import_viem8 = require("viem");
2447
+ var import_viem11 = require("viem");
2118
2448
  function createIssuerService(config) {
2119
2449
  if (!config.provider) {
2120
2450
  throw new Error("createIssuerService: provider is required");
@@ -2140,7 +2470,7 @@ function createIssuerService(config) {
2140
2470
  "createIssuerService: at least one of pointTokenAddress / pointTokenAddresses is required"
2141
2471
  );
2142
2472
  }
2143
- const tokenAddresses = rawAddresses.map((a) => (0, import_viem8.getAddress)(a));
2473
+ const tokenAddresses = rawAddresses.map((a) => (0, import_viem11.getAddress)(a));
2144
2474
  const ledger = config.ledger ?? new MemoryPointLedger();
2145
2475
  const sessionStore = config.sessionStore ?? new MemorySessionStore();
2146
2476
  const policy = config.policy ?? new DefaultPolicyEngine({ ledger });
@@ -2258,12 +2588,16 @@ var PAFI_ISSUER_SDK_VERSION = "0.1.0";
2258
2588
  MintingGatewayError,
2259
2589
  NonceManager,
2260
2590
  PAFI_ISSUER_SDK_VERSION,
2591
+ PTRedeemError,
2592
+ PTRedeemHandler,
2261
2593
  PafiBackendClient,
2262
2594
  PafiBackendError,
2263
2595
  PointIndexer,
2264
2596
  PrivateKeySigner,
2265
2597
  RelayError,
2266
2598
  RelayService,
2599
+ TopUpRedemptionError,
2600
+ TopUpRedemptionHandler,
2267
2601
  authenticateRequest,
2268
2602
  createIssuerService,
2269
2603
  createSubgraphNativeUsdtQuoter,