@pafi-dev/issuer 0.22.1 → 0.24.1

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.js CHANGED
@@ -579,12 +579,14 @@ import {
579
579
  erc20Abi
580
580
  } from "viem";
581
581
  import {
582
- POINT_TOKEN_ABI,
582
+ POINT_TOKEN_MINT_SIG_ABI,
583
+ POINT_TOKEN_BURN_SIG_ABI,
583
584
  mintFeeWrapperAbi,
584
585
  buildPartialUserOperation,
585
586
  signMintRequest,
586
587
  getContractAddresses,
587
- quoteOperatorFeePt
588
+ quoteOperatorFeePt,
589
+ Source
588
590
  } from "@pafi-dev/core";
589
591
  var RelayService = class {
590
592
  provider;
@@ -673,6 +675,7 @@ var RelayService = class {
673
675
  "prepareMint: deadline exceeds maximum allowed window (1 hour)"
674
676
  );
675
677
  }
678
+ const MINT_SOURCE = Source.EQUITY;
676
679
  const useWrapper = params.mintFeeWrapperAddress !== void 0;
677
680
  const receiverForSig = useWrapper ? params.mintFeeWrapperAddress : params.userAddress;
678
681
  let minterSig;
@@ -684,6 +687,7 @@ var RelayService = class {
684
687
  user: params.userAddress,
685
688
  receiver: receiverForSig,
686
689
  amount: params.amount,
690
+ source: MINT_SOURCE,
687
691
  nonce: params.mintRequestNonce,
688
692
  deadline: params.deadline
689
693
  }
@@ -714,9 +718,15 @@ var RelayService = class {
714
718
  mintTarget = params.mintFeeWrapperAddress;
715
719
  } else {
716
720
  mintCallData = encodeFunctionData({
717
- abi: POINT_TOKEN_ABI,
721
+ abi: POINT_TOKEN_MINT_SIG_ABI,
718
722
  functionName: "mint",
719
- args: [params.userAddress, params.amount, params.deadline, minterSig]
723
+ args: [
724
+ params.userAddress,
725
+ params.amount,
726
+ MINT_SOURCE,
727
+ params.deadline,
728
+ minterSig
729
+ ]
720
730
  });
721
731
  mintTarget = params.pointTokenAddress;
722
732
  }
@@ -801,11 +811,12 @@ var RelayService = class {
801
811
  let burnCallData;
802
812
  try {
803
813
  burnCallData = encodeFunctionData({
804
- abi: POINT_TOKEN_ABI,
814
+ abi: POINT_TOKEN_BURN_SIG_ABI,
805
815
  functionName: "burn",
806
816
  args: [
807
817
  params.burnRequest.from,
808
818
  params.burnRequest.amount,
819
+ params.burnRequest.source,
809
820
  params.burnRequest.deadline,
810
821
  params.burnerSignature
811
822
  ]
@@ -900,11 +911,12 @@ var RelayService = class {
900
911
  mintTarget = params.mintFeeWrapperAddress;
901
912
  } else {
902
913
  mintCallData = encodeFunctionData({
903
- abi: POINT_TOKEN_ABI,
914
+ abi: POINT_TOKEN_MINT_SIG_ABI,
904
915
  functionName: "mint",
905
916
  args: [
906
917
  params.userAddress,
907
918
  params.amount,
919
+ Source.EQUITY,
908
920
  params.deadline,
909
921
  PLACEHOLDER_SIG_65
910
922
  ]
@@ -926,11 +938,12 @@ var RelayService = class {
926
938
  /** Burn-side mirror of `previewMintUserOp`. */
927
939
  previewBurnUserOp(params) {
928
940
  const burnCallData = encodeFunctionData({
929
- abi: POINT_TOKEN_ABI,
941
+ abi: POINT_TOKEN_BURN_SIG_ABI,
930
942
  functionName: "burn",
931
943
  args: [
932
944
  params.userAddress,
933
945
  params.amount,
946
+ Source.EQUITY,
934
947
  params.deadline,
935
948
  PLACEHOLDER_SIG_65
936
949
  ]
@@ -1122,18 +1135,42 @@ function createPafiEstimatorClient(config) {
1122
1135
  }
1123
1136
 
1124
1137
  // src/indexer/types.ts
1125
- var InMemoryCursorStore = class {
1138
+ var InMemoryCursorStore = class _InMemoryCursorStore {
1126
1139
  cursor;
1140
+ /**
1141
+ * Child stores keyed by `forKey()`. Each child has its own cursor
1142
+ * (the H-05 fix), so a single InMemoryCursorStore can back N
1143
+ * PointIndexers in tests / single-process callers.
1144
+ */
1145
+ children = /* @__PURE__ */ new Map();
1127
1146
  async load() {
1128
1147
  return this.cursor;
1129
1148
  }
1130
1149
  async save(blockNumber) {
1131
1150
  this.cursor = blockNumber;
1132
1151
  }
1152
+ forKey(key) {
1153
+ let child = this.children.get(key);
1154
+ if (!child) {
1155
+ child = new _InMemoryCursorStore();
1156
+ this.children.set(key, child);
1157
+ }
1158
+ return child;
1159
+ }
1133
1160
  };
1134
1161
 
1135
1162
  // src/indexer/pointIndexer.ts
1136
1163
  import { getAddress as getAddress3, parseAbiItem } from "viem";
1164
+ var PointIndexerFinalizeError = class extends Error {
1165
+ constructor(message, context, cause) {
1166
+ super(message);
1167
+ this.context = context;
1168
+ this.cause = cause;
1169
+ this.name = "PointIndexerFinalizeError";
1170
+ }
1171
+ context;
1172
+ cause;
1173
+ };
1137
1174
  var TRANSFER_EVENT = parseAbiItem(
1138
1175
  "event Transfer(address indexed from, address indexed to, uint256 value)"
1139
1176
  );
@@ -1359,8 +1396,18 @@ var PointIndexer = class {
1359
1396
  evt.txHash,
1360
1397
  this.pointTokenAddress
1361
1398
  );
1362
- } catch {
1363
- return;
1399
+ } catch (err) {
1400
+ throw new PointIndexerFinalizeError(
1401
+ `PointIndexer.deductBalance failed for tx ${evt.txHash} (to=${evt.to}, amount=${evt.amount}, block=${evt.blockNumber}); cursor will NOT advance, next tick retries.`,
1402
+ {
1403
+ pointToken: this.pointTokenAddress,
1404
+ to: evt.to,
1405
+ amount: evt.amount,
1406
+ txHash: evt.txHash,
1407
+ blockNumber: evt.blockNumber
1408
+ },
1409
+ err
1410
+ );
1364
1411
  }
1365
1412
  try {
1366
1413
  await this.ledger.updateMintStatus(match.lockId, "MINTED", evt.txHash);
@@ -1382,6 +1429,16 @@ function pickMatchingLock(locks, amount) {
1382
1429
 
1383
1430
  // src/indexer/burnIndexer.ts
1384
1431
  import { getAddress as getAddress4, parseAbiItem as parseAbiItem2 } from "viem";
1432
+ var BurnIndexerFinalizeError = class extends Error {
1433
+ constructor(message, context, cause) {
1434
+ super(message);
1435
+ this.context = context;
1436
+ this.cause = cause;
1437
+ this.name = "BurnIndexerFinalizeError";
1438
+ }
1439
+ context;
1440
+ cause;
1441
+ };
1385
1442
  var TRANSFER_EVENT2 = parseAbiItem2(
1386
1443
  "event Transfer(address indexed from, address indexed to, uint256 value)"
1387
1444
  );
@@ -1393,7 +1450,7 @@ var BurnIndexer = class {
1393
1450
  provider;
1394
1451
  /**
1395
1452
  * The PointToken this indexer watches. Exposed so callers can key
1396
- * leader-election locks / cursor stores by token (audit H-04 fix).
1453
+ * leader-election locks / cursor stores by token
1397
1454
  */
1398
1455
  pointTokenAddress;
1399
1456
  ledger;
@@ -1549,7 +1606,18 @@ var BurnIndexer = class {
1549
1606
  try {
1550
1607
  await this.ledger.resolveCreditByBurnTx(lockId, evt.txHash);
1551
1608
  } catch (err) {
1552
- console.error("[PAFI] BurnIndexer finalize error \u2014 credit may be lost:", err);
1609
+ throw new BurnIndexerFinalizeError(
1610
+ `BurnIndexer.resolveCreditByBurnTx failed for tx ${evt.txHash} (lockId=${lockId}, from=${evt.from}, amount=${evt.amount}, block=${evt.blockNumber}); cursor will NOT advance, next tick retries.`,
1611
+ {
1612
+ pointToken: this.pointTokenAddress,
1613
+ from: evt.from,
1614
+ amount: evt.amount,
1615
+ txHash: evt.txHash,
1616
+ blockNumber: evt.blockNumber,
1617
+ lockId
1618
+ },
1619
+ err
1620
+ );
1553
1621
  }
1554
1622
  }
1555
1623
  };
@@ -2013,9 +2081,10 @@ var PointTokenDomainResolver = class {
2013
2081
  import { getAddress as getAddress7 } from "viem";
2014
2082
  import {
2015
2083
  signBurnRequest,
2016
- POINT_TOKEN_ABI as POINT_TOKEN_ABI2,
2084
+ POINT_TOKEN_ABI,
2017
2085
  getPointTokenBalance as getPointTokenBalance2,
2018
- getContractAddresses as getContractAddresses2
2086
+ getContractAddresses as getContractAddresses2,
2087
+ Source as Source2
2019
2088
  } from "@pafi-dev/core";
2020
2089
  var DEFAULT_REDEEM_LOCK_MS = 15 * 60 * 1e3;
2021
2090
  var DEFAULT_SIG_DEADLINE_SEC = 15 * 60;
@@ -2119,7 +2188,7 @@ var PTRedeemHandler = class {
2119
2188
  try {
2120
2189
  burnNonce = await this.provider.readContract({
2121
2190
  address: pointTokenAddress,
2122
- abi: POINT_TOKEN_ABI2,
2191
+ abi: POINT_TOKEN_ABI,
2123
2192
  functionName: "burnRequestNonces",
2124
2193
  args: [request.userAddress]
2125
2194
  });
@@ -2201,10 +2270,12 @@ var PTRedeemHandler = class {
2201
2270
  chainId: this.chainId,
2202
2271
  verifyingContract: pointTokenAddress
2203
2272
  };
2273
+ const BURN_SOURCE = Source2.EQUITY;
2204
2274
  const sponsoredBurnAmount = request.amount - fee;
2205
2275
  const sponsoredBurnRequest = {
2206
2276
  from: request.userAddress,
2207
2277
  amount: sponsoredBurnAmount,
2278
+ source: BURN_SOURCE,
2208
2279
  nonce: burnNonce,
2209
2280
  deadline
2210
2281
  };
@@ -2240,6 +2311,7 @@ var PTRedeemHandler = class {
2240
2311
  const fallbackBurnRequest = {
2241
2312
  from: request.userAddress,
2242
2313
  amount: request.amount,
2314
+ source: BURN_SOURCE,
2243
2315
  nonce: burnNonce,
2244
2316
  deadline
2245
2317
  };
@@ -4567,6 +4639,13 @@ async function createIssuerService(config) {
4567
4639
  const sdkWrapperAddress = getContractAddresses7(config.chainId).mintFeeWrapper;
4568
4640
  const wrapperOverride = config.indexer?.mintFeeWrapperAddress;
4569
4641
  const resolvedWrapperAddress = wrapperOverride !== void 0 ? wrapperOverride : sdkWrapperAddress;
4642
+ const baseCursorStore = config.indexer?.cursorStore;
4643
+ const sharedCursorWithMultipleTokens = baseCursorStore !== void 0 && typeof baseCursorStore.forKey !== "function" && tokenAddresses.length > 1;
4644
+ if (sharedCursorWithMultipleTokens) {
4645
+ console.warn(
4646
+ `[@pafi-dev/issuer] cursorStore lacks forKey() and ${tokenAddresses.length} PointTokens are configured. All PointIndexers will share one cursor row, causing token-skipping (audit finding H-05). Implement IIndexerCursorStore.forKey to return per-token derived stores. This permissive path will be removed in a future major release.`
4647
+ );
4648
+ }
4570
4649
  const indexers = /* @__PURE__ */ new Map();
4571
4650
  for (const tokenAddress of tokenAddresses) {
4572
4651
  const indexerConfig = {
@@ -4580,8 +4659,10 @@ async function createIssuerService(config) {
4580
4659
  if (config.indexer?.fromBlock !== void 0) {
4581
4660
  indexerConfig.fromBlock = config.indexer.fromBlock;
4582
4661
  }
4583
- if (config.indexer?.cursorStore) {
4584
- indexerConfig.cursorStore = config.indexer.cursorStore;
4662
+ if (baseCursorStore) {
4663
+ indexerConfig.cursorStore = typeof baseCursorStore.forKey === "function" ? baseCursorStore.forKey(
4664
+ `point-indexer:${tokenAddress.toLowerCase()}`
4665
+ ) : baseCursorStore;
4585
4666
  }
4586
4667
  if (config.indexer?.confirmations !== void 0) {
4587
4668
  indexerConfig.confirmations = config.indexer.confirmations;
@@ -4678,10 +4759,9 @@ async function createIssuerService(config) {
4678
4759
  // src/issuer-state/validator.ts
4679
4760
  import { getAddress as getAddress13 } from "viem";
4680
4761
  import {
4681
- POINT_TOKEN_ABI as POINT_TOKEN_ABI3,
4762
+ POINT_TOKEN_ABI as POINT_TOKEN_ABI2,
4682
4763
  issuerRegistryAbi,
4683
- getContractAddresses as getContractAddresses8,
4684
- getTokenCap
4764
+ getContractAddresses as getContractAddresses8
4685
4765
  } from "@pafi-dev/core";
4686
4766
  var ISSUER_RECORD_TTL_MS = 3e4;
4687
4767
  var IssuerStateValidator = class _IssuerStateValidator {
@@ -4728,7 +4808,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
4728
4808
  if (cached) return cached;
4729
4809
  const issuer = await this.provider.readContract({
4730
4810
  address: key,
4731
- abi: POINT_TOKEN_ABI3,
4811
+ abi: POINT_TOKEN_ABI2,
4732
4812
  functionName: "issuer"
4733
4813
  });
4734
4814
  this.pointTokenIssuerCache.set(key, getAddress13(issuer));
@@ -4782,22 +4862,22 @@ var IssuerStateValidator = class _IssuerStateValidator {
4782
4862
  }
4783
4863
  throw err;
4784
4864
  }
4785
- const { issuer, totalSupply, hardCap, remaining } = state;
4865
+ const { issuer, equityCap, equitySupply, remaining } = state;
4786
4866
  if (!issuer.active) {
4787
4867
  throw new IssuerStateError(
4788
4868
  "ISSUER_INACTIVE",
4789
- `Issuer ${issuer.issuerAddress} is deactivated on IssuerRegistry`,
4790
- { issuer: issuer.issuerAddress, pointToken: issuer.pointToken }
4869
+ `Issuer "${issuer.name}" is deactivated on IssuerRegistry`,
4870
+ { pointToken }
4791
4871
  );
4792
4872
  }
4793
- if (totalSupply + amount > hardCap) {
4873
+ if (equitySupply + amount > equityCap.hardCap) {
4794
4874
  throw new IssuerStateError(
4795
4875
  "MINT_CAP_EXCEEDED",
4796
- `Requested ${amount} PT would exceed mint cap. Cap=${hardCap}, minted=${totalSupply}, remaining=${remaining}`,
4876
+ `Requested ${amount} PT would exceed EQUITY mint cap. Cap=${equityCap.hardCap}, equityMinted=${equitySupply}, remaining=${remaining}`,
4797
4877
  {
4798
4878
  requested: amount.toString(),
4799
- cap: hardCap.toString(),
4800
- minted: totalSupply.toString(),
4879
+ cap: equityCap.hardCap.toString(),
4880
+ equityMinted: equitySupply.toString(),
4801
4881
  remaining: remaining.toString()
4802
4882
  }
4803
4883
  );
@@ -4813,33 +4893,28 @@ var IssuerStateValidator = class _IssuerStateValidator {
4813
4893
  args: [issuerAddr]
4814
4894
  });
4815
4895
  const issuer = {
4816
- issuerAddress: issuerStruct.issuerAddress,
4817
4896
  signerAddress: issuerStruct.signerAddress,
4818
4897
  name: issuerStruct.name,
4819
- symbol: issuerStruct.symbol,
4820
4898
  active: issuerStruct.active,
4821
- pointToken: issuerStruct.pointToken,
4822
- mintingOracle: issuerStruct.mintingOracle
4899
+ capitalBase: issuerStruct.capitalBase,
4900
+ basisPoints: Number(issuerStruct.basisPoints)
4823
4901
  };
4824
- const [tokenCap, totalSupply] = await Promise.all([
4825
- getTokenCap(this.provider, issuer.mintingOracle, tokenAddr),
4826
- this.provider.readContract({
4827
- address: tokenAddr,
4828
- abi: POINT_TOKEN_ABI3,
4829
- functionName: "totalSupply"
4830
- })
4831
- ]);
4832
- const tokenCapRecord = {
4833
- declaredTotalSupply: tokenCap.declaredTotalSupply,
4834
- capBasisPoints: tokenCap.capBasisPoints
4902
+ const equitySupply = await this.provider.readContract({
4903
+ address: tokenAddr,
4904
+ abi: POINT_TOKEN_ABI2,
4905
+ functionName: "equitySupply"
4906
+ });
4907
+ const hardCap = issuer.capitalBase * BigInt(issuer.basisPoints) / 10000n;
4908
+ const equityCap = {
4909
+ capitalBase: issuer.capitalBase,
4910
+ basisPoints: issuer.basisPoints,
4911
+ hardCap
4835
4912
  };
4836
- const hardCap = tokenCapRecord.declaredTotalSupply * BigInt(tokenCapRecord.capBasisPoints) / 10000n;
4837
- const remaining = hardCap > totalSupply ? hardCap - totalSupply : 0n;
4913
+ const remaining = hardCap > equitySupply ? hardCap - equitySupply : 0n;
4838
4914
  return {
4839
4915
  issuer,
4840
- tokenCap: tokenCapRecord,
4841
- totalSupply,
4842
- hardCap,
4916
+ equityCap,
4917
+ equitySupply,
4843
4918
  remaining
4844
4919
  };
4845
4920
  }
@@ -4882,7 +4957,7 @@ var MemoryRedemptionHistoryStore = class {
4882
4957
  };
4883
4958
 
4884
4959
  // src/index.ts
4885
- var PAFI_ISSUER_SDK_VERSION = true ? "0.22.1" : "dev";
4960
+ var PAFI_ISSUER_SDK_VERSION = true ? "0.24.1" : "dev";
4886
4961
  export {
4887
4962
  AdapterMisconfiguredError,
4888
4963
  AuthError,
@@ -4890,6 +4965,7 @@ export {
4890
4965
  BundlerNotConfiguredError,
4891
4966
  BundlerRejectedError,
4892
4967
  BurnIndexer,
4968
+ BurnIndexerFinalizeError,
4893
4969
  ConfigurationError,
4894
4970
  DEFAULT_REDEMPTION_POLICY,
4895
4971
  DefaultPolicyEngine,
@@ -4921,6 +4997,7 @@ export {
4921
4997
  PerpDepositError,
4922
4998
  PerpDepositHandler,
4923
4999
  PointIndexer,
5000
+ PointIndexerFinalizeError,
4924
5001
  PointTokenDomainResolver,
4925
5002
  PolicyProvider,
4926
5003
  REDEMPTION_HISTORY_WINDOW_SEC,