@pafi-dev/issuer 0.10.2 → 0.11.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.d.cts CHANGED
@@ -814,6 +814,22 @@ interface PointIndexerConfig {
814
814
  provider: PublicClient;
815
815
  pointTokenAddress: Address;
816
816
  ledger: IPointLedger;
817
+ /**
818
+ * v1.6 — when set, indexer listens to `MintFeeWrapper.MintWithFee`
819
+ * (filtered by this `pointToken`) instead of `PointToken.Transfer(0x0)`.
820
+ *
821
+ * Required for wrapper-mediated mints because the on-chain Transfer
822
+ * destination is the wrapper itself (not the end user), so a naive
823
+ * `Transfer(0x0 → user)` watch would leave PENDING locks unresolved.
824
+ *
825
+ * `MintWithFee(indexed pointToken, indexed to, grossAmount, netAmount,
826
+ * feeAmount)` carries the actual recipient + the gross amount that
827
+ * matches the off-chain lock.
828
+ *
829
+ * Pass `undefined` (or the dead-zero address) for direct-mint chains
830
+ * without a wrapper — indexer falls back to legacy Transfer mode.
831
+ */
832
+ mintFeeWrapperAddress?: Address;
817
833
  /**
818
834
  * Block to start from on first run. Ignored if the cursor store already
819
835
  * has a value. Defaults to `0n`.
@@ -853,8 +869,20 @@ interface PointIndexerConfig {
853
869
  onTickError?: (err: unknown) => void;
854
870
  }
855
871
  /**
856
- * Watches `PointToken.Transfer(from=0x0 to)` events and finalizes the
857
- * issuer ledger on each confirmed mint.
872
+ * Watches mint events on PointToken and finalizes the issuer ledger when
873
+ * a confirmed mint matches a PENDING lock.
874
+ *
875
+ * **Two modes** — selected at construction by `mintFeeWrapperAddress`:
876
+ *
877
+ * 1. **Wrapper mode (v1.6, recommended for mainnet)**
878
+ * Listens to `MintFeeWrapper.MintWithFee(indexed pointToken, indexed to,
879
+ * grossAmount, netAmount, feeAmount)` filtered by `pointToken`. The
880
+ * `to` field is the actual end-user (not the wrapper), and `grossAmount`
881
+ * matches the off-chain lock's amount.
882
+ *
883
+ * 2. **Direct mode (legacy / chains without wrapper)**
884
+ * Listens to `PointToken.Transfer(from=0x0 → to)` — the original v1.5
885
+ * behavior. Used when the wrapper address is undefined / zero / dead.
858
886
  *
859
887
  * Finalization strategy (per event):
860
888
  * 1. Find a PENDING locked mint request for `to` with matching amount.
@@ -876,6 +904,7 @@ interface PointIndexerConfig {
876
904
  declare class PointIndexer {
877
905
  private readonly provider;
878
906
  private readonly pointTokenAddress;
907
+ private readonly mintFeeWrapperAddress;
879
908
  private readonly ledger;
880
909
  private readonly cursorStore;
881
910
  private readonly startBlock;
@@ -904,7 +933,18 @@ declare class PointIndexer {
904
933
  * engaging `start()`. On completion, the cursor is advanced to `to + 1`.
905
934
  */
906
935
  processBlockRange(from: bigint, to: bigint): Promise<void>;
907
- private decodeMintEvents;
936
+ /**
937
+ * Wrapper mode (v1.6): listen for `MintWithFee` on the wrapper,
938
+ * filtered to events for THIS pointToken only. The event's `to` field
939
+ * is the actual end user, and `grossAmount` matches the lock amount.
940
+ */
941
+ private fetchWrapperMintEvents;
942
+ /**
943
+ * Direct mode (legacy / chains without wrapper): listen for
944
+ * `Transfer(from=0x0 → to)` on the PointToken itself.
945
+ */
946
+ private fetchTransferMintEvents;
947
+ private decodeTransferMintEvents;
908
948
  /**
909
949
  * Finalize a single mint event: match it to a PENDING lock in the
910
950
  * ledger, then call `deductBalance` (which also resolves the lock in
@@ -2550,6 +2590,14 @@ interface IssuerServiceConfig {
2550
2590
  * Default: `false` — the caller decides when to begin polling.
2551
2591
  */
2552
2592
  autoStart?: boolean;
2593
+ /**
2594
+ * v1.6 — override the MintFeeWrapper address used by the indexer.
2595
+ * When omitted, the factory auto-resolves from
2596
+ * `getContractAddresses(chainId).mintFeeWrapper`. Pass the
2597
+ * dead-zero address (`0x...dEaD`) to force direct-Transfer mode
2598
+ * (legacy v1.5, useful for local fork tests).
2599
+ */
2600
+ mintFeeWrapperAddress?: Address;
2553
2601
  };
2554
2602
  /**
2555
2603
  * Redemption restriction config. When provided, the SDK fetches the
package/dist/index.d.ts CHANGED
@@ -814,6 +814,22 @@ interface PointIndexerConfig {
814
814
  provider: PublicClient;
815
815
  pointTokenAddress: Address;
816
816
  ledger: IPointLedger;
817
+ /**
818
+ * v1.6 — when set, indexer listens to `MintFeeWrapper.MintWithFee`
819
+ * (filtered by this `pointToken`) instead of `PointToken.Transfer(0x0)`.
820
+ *
821
+ * Required for wrapper-mediated mints because the on-chain Transfer
822
+ * destination is the wrapper itself (not the end user), so a naive
823
+ * `Transfer(0x0 → user)` watch would leave PENDING locks unresolved.
824
+ *
825
+ * `MintWithFee(indexed pointToken, indexed to, grossAmount, netAmount,
826
+ * feeAmount)` carries the actual recipient + the gross amount that
827
+ * matches the off-chain lock.
828
+ *
829
+ * Pass `undefined` (or the dead-zero address) for direct-mint chains
830
+ * without a wrapper — indexer falls back to legacy Transfer mode.
831
+ */
832
+ mintFeeWrapperAddress?: Address;
817
833
  /**
818
834
  * Block to start from on first run. Ignored if the cursor store already
819
835
  * has a value. Defaults to `0n`.
@@ -853,8 +869,20 @@ interface PointIndexerConfig {
853
869
  onTickError?: (err: unknown) => void;
854
870
  }
855
871
  /**
856
- * Watches `PointToken.Transfer(from=0x0 to)` events and finalizes the
857
- * issuer ledger on each confirmed mint.
872
+ * Watches mint events on PointToken and finalizes the issuer ledger when
873
+ * a confirmed mint matches a PENDING lock.
874
+ *
875
+ * **Two modes** — selected at construction by `mintFeeWrapperAddress`:
876
+ *
877
+ * 1. **Wrapper mode (v1.6, recommended for mainnet)**
878
+ * Listens to `MintFeeWrapper.MintWithFee(indexed pointToken, indexed to,
879
+ * grossAmount, netAmount, feeAmount)` filtered by `pointToken`. The
880
+ * `to` field is the actual end-user (not the wrapper), and `grossAmount`
881
+ * matches the off-chain lock's amount.
882
+ *
883
+ * 2. **Direct mode (legacy / chains without wrapper)**
884
+ * Listens to `PointToken.Transfer(from=0x0 → to)` — the original v1.5
885
+ * behavior. Used when the wrapper address is undefined / zero / dead.
858
886
  *
859
887
  * Finalization strategy (per event):
860
888
  * 1. Find a PENDING locked mint request for `to` with matching amount.
@@ -876,6 +904,7 @@ interface PointIndexerConfig {
876
904
  declare class PointIndexer {
877
905
  private readonly provider;
878
906
  private readonly pointTokenAddress;
907
+ private readonly mintFeeWrapperAddress;
879
908
  private readonly ledger;
880
909
  private readonly cursorStore;
881
910
  private readonly startBlock;
@@ -904,7 +933,18 @@ declare class PointIndexer {
904
933
  * engaging `start()`. On completion, the cursor is advanced to `to + 1`.
905
934
  */
906
935
  processBlockRange(from: bigint, to: bigint): Promise<void>;
907
- private decodeMintEvents;
936
+ /**
937
+ * Wrapper mode (v1.6): listen for `MintWithFee` on the wrapper,
938
+ * filtered to events for THIS pointToken only. The event's `to` field
939
+ * is the actual end user, and `grossAmount` matches the lock amount.
940
+ */
941
+ private fetchWrapperMintEvents;
942
+ /**
943
+ * Direct mode (legacy / chains without wrapper): listen for
944
+ * `Transfer(from=0x0 → to)` on the PointToken itself.
945
+ */
946
+ private fetchTransferMintEvents;
947
+ private decodeTransferMintEvents;
908
948
  /**
909
949
  * Finalize a single mint event: match it to a PENDING lock in the
910
950
  * ledger, then call `deductBalance` (which also resolves the lock in
@@ -2550,6 +2590,14 @@ interface IssuerServiceConfig {
2550
2590
  * Default: `false` — the caller decides when to begin polling.
2551
2591
  */
2552
2592
  autoStart?: boolean;
2593
+ /**
2594
+ * v1.6 — override the MintFeeWrapper address used by the indexer.
2595
+ * When omitted, the factory auto-resolves from
2596
+ * `getContractAddresses(chainId).mintFeeWrapper`. Pass the
2597
+ * dead-zero address (`0x...dEaD`) to force direct-Transfer mode
2598
+ * (legacy v1.5, useful for local fork tests).
2599
+ */
2600
+ mintFeeWrapperAddress?: Address;
2553
2601
  };
2554
2602
  /**
2555
2603
  * Redemption restriction config. When provided, the SDK fetches the
package/dist/index.js CHANGED
@@ -924,13 +924,23 @@ import { getAddress as getAddress3, parseAbiItem } from "viem";
924
924
  var TRANSFER_EVENT = parseAbiItem(
925
925
  "event Transfer(address indexed from, address indexed to, uint256 value)"
926
926
  );
927
+ var MINT_WITH_FEE_EVENT = parseAbiItem(
928
+ "event MintWithFee(address indexed pointToken, address indexed to, uint256 grossAmount, uint256 netAmount, uint256 feeAmount)"
929
+ );
927
930
  var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
931
+ var DEAD_ADDRESS = "0x000000000000000000000000000000000000dEaD";
928
932
  var DEFAULT_CONFIRMATIONS = 3;
929
933
  var DEFAULT_BATCH_SIZE = 2000n;
930
934
  var DEFAULT_POLL_INTERVAL_MS = 5e3;
935
+ function isNoWrapper(addr) {
936
+ if (!addr) return true;
937
+ const checksummed = getAddress3(addr);
938
+ return checksummed === ZERO_ADDRESS || checksummed === DEAD_ADDRESS;
939
+ }
931
940
  var PointIndexer = class {
932
941
  provider;
933
942
  pointTokenAddress;
943
+ mintFeeWrapperAddress;
934
944
  ledger;
935
945
  cursorStore;
936
946
  startBlock;
@@ -946,7 +956,8 @@ var PointIndexer = class {
946
956
  throw new Error("PointIndexer: pointTokenAddress required");
947
957
  if (!config.ledger) throw new Error("PointIndexer: ledger required");
948
958
  this.provider = config.provider;
949
- this.pointTokenAddress = config.pointTokenAddress;
959
+ this.pointTokenAddress = getAddress3(config.pointTokenAddress);
960
+ this.mintFeeWrapperAddress = isNoWrapper(config.mintFeeWrapperAddress) ? void 0 : getAddress3(config.mintFeeWrapperAddress);
950
961
  this.ledger = config.ledger;
951
962
  this.cursorStore = config.cursorStore ?? new InMemoryCursorStore();
952
963
  this.startBlock = config.fromBlock ?? 0n;
@@ -1029,14 +1040,7 @@ var PointIndexer = class {
1029
1040
  let cursor = from;
1030
1041
  while (cursor <= to) {
1031
1042
  const chunkEnd = cursor + this.batchSize - 1n > to ? to : cursor + this.batchSize - 1n;
1032
- const logs = await this.provider.getLogs({
1033
- address: this.pointTokenAddress,
1034
- event: TRANSFER_EVENT,
1035
- args: { from: ZERO_ADDRESS },
1036
- fromBlock: cursor,
1037
- toBlock: chunkEnd
1038
- });
1039
- const events = this.decodeMintEvents(logs);
1043
+ const events = this.mintFeeWrapperAddress ? await this.fetchWrapperMintEvents(cursor, chunkEnd) : await this.fetchTransferMintEvents(cursor, chunkEnd);
1040
1044
  events.sort((a, b) => {
1041
1045
  if (a.blockNumber !== b.blockNumber) {
1042
1046
  return a.blockNumber < b.blockNumber ? -1 : 1;
@@ -1051,9 +1055,53 @@ var PointIndexer = class {
1051
1055
  }
1052
1056
  }
1053
1057
  // -------------------------------------------------------------------------
1054
- // Internals
1058
+ // Event fetching — two modes (wrapper vs direct)
1055
1059
  // -------------------------------------------------------------------------
1056
- decodeMintEvents(logs) {
1060
+ /**
1061
+ * Wrapper mode (v1.6): listen for `MintWithFee` on the wrapper,
1062
+ * filtered to events for THIS pointToken only. The event's `to` field
1063
+ * is the actual end user, and `grossAmount` matches the lock amount.
1064
+ */
1065
+ async fetchWrapperMintEvents(fromBlock, toBlock) {
1066
+ const logs = await this.provider.getLogs({
1067
+ address: this.mintFeeWrapperAddress,
1068
+ event: MINT_WITH_FEE_EVENT,
1069
+ args: { pointToken: this.pointTokenAddress },
1070
+ fromBlock,
1071
+ toBlock
1072
+ });
1073
+ const out = [];
1074
+ for (const log of logs) {
1075
+ const args = log.args;
1076
+ if (!args.pointToken || !args.to || args.grossAmount === void 0 || log.blockNumber === null || log.transactionHash === null) {
1077
+ continue;
1078
+ }
1079
+ if (getAddress3(args.pointToken) !== this.pointTokenAddress) continue;
1080
+ out.push({
1081
+ to: getAddress3(args.to),
1082
+ amount: args.grossAmount,
1083
+ blockNumber: log.blockNumber,
1084
+ txHash: log.transactionHash,
1085
+ logIndex: log.logIndex ?? 0
1086
+ });
1087
+ }
1088
+ return out;
1089
+ }
1090
+ /**
1091
+ * Direct mode (legacy / chains without wrapper): listen for
1092
+ * `Transfer(from=0x0 → to)` on the PointToken itself.
1093
+ */
1094
+ async fetchTransferMintEvents(fromBlock, toBlock) {
1095
+ const logs = await this.provider.getLogs({
1096
+ address: this.pointTokenAddress,
1097
+ event: TRANSFER_EVENT,
1098
+ args: { from: ZERO_ADDRESS },
1099
+ fromBlock,
1100
+ toBlock
1101
+ });
1102
+ return this.decodeTransferMintEvents(logs);
1103
+ }
1104
+ decodeTransferMintEvents(logs) {
1057
1105
  const out = [];
1058
1106
  for (const log of logs) {
1059
1107
  const args = log.args;
@@ -1070,6 +1118,9 @@ var PointIndexer = class {
1070
1118
  }
1071
1119
  return out;
1072
1120
  }
1121
+ // -------------------------------------------------------------------------
1122
+ // Finalization
1123
+ // -------------------------------------------------------------------------
1073
1124
  /**
1074
1125
  * Finalize a single mint event: match it to a PENDING lock in the
1075
1126
  * ledger, then call `deductBalance` (which also resolves the lock in
@@ -2380,7 +2431,7 @@ var PTClaimError = class extends PafiSdkError {
2380
2431
  this.details = details;
2381
2432
  }
2382
2433
  };
2383
- function isNoWrapper(address) {
2434
+ function isNoWrapper2(address) {
2384
2435
  if (!address) return true;
2385
2436
  const lower = address.toLowerCase();
2386
2437
  return lower === "0x0000000000000000000000000000000000000000" || lower === "0x000000000000000000000000000000000000dead";
@@ -2425,7 +2476,7 @@ var PTClaimHandler = class {
2425
2476
  const { batchExecutor: batchExecutorAddress } = chainAddresses;
2426
2477
  const wrapperOverride = this.cfg.mintFeeWrapperAddress;
2427
2478
  const wrapperFromSdk = chainAddresses.mintFeeWrapper;
2428
- const resolvedWrapper = wrapperOverride !== void 0 ? isNoWrapper(wrapperOverride) ? void 0 : wrapperOverride : isNoWrapper(wrapperFromSdk) ? void 0 : wrapperFromSdk;
2479
+ const resolvedWrapper = wrapperOverride !== void 0 ? isNoWrapper2(wrapperOverride) ? void 0 : wrapperOverride : isNoWrapper2(wrapperFromSdk) ? void 0 : wrapperFromSdk;
2429
2480
  const lockId = await this.cfg.ledger.lockForMinting(
2430
2481
  request.userAddress,
2431
2482
  request.amount,
@@ -4140,6 +4191,9 @@ function createIssuerService(config) {
4140
4191
  provider: config.provider
4141
4192
  });
4142
4193
  }
4194
+ const sdkWrapperAddress = getContractAddresses7(config.chainId).mintFeeWrapper;
4195
+ const wrapperOverride = config.indexer?.mintFeeWrapperAddress;
4196
+ const resolvedWrapperAddress = wrapperOverride !== void 0 ? wrapperOverride : sdkWrapperAddress;
4143
4197
  const indexers = /* @__PURE__ */ new Map();
4144
4198
  for (const tokenAddress of tokenAddresses) {
4145
4199
  const indexerConfig = {
@@ -4147,6 +4201,9 @@ function createIssuerService(config) {
4147
4201
  pointTokenAddress: tokenAddress,
4148
4202
  ledger
4149
4203
  };
4204
+ if (resolvedWrapperAddress !== void 0) {
4205
+ indexerConfig.mintFeeWrapperAddress = resolvedWrapperAddress;
4206
+ }
4150
4207
  if (config.indexer?.fromBlock !== void 0) {
4151
4208
  indexerConfig.fromBlock = config.indexer.fromBlock;
4152
4209
  }
@@ -4421,7 +4478,7 @@ var MemoryRedemptionHistoryStore = class {
4421
4478
  };
4422
4479
 
4423
4480
  // src/index.ts
4424
- var PAFI_ISSUER_SDK_VERSION = true ? "0.10.2" : "dev";
4481
+ var PAFI_ISSUER_SDK_VERSION = true ? "0.11.0" : "dev";
4425
4482
  export {
4426
4483
  AdapterMisconfiguredError,
4427
4484
  AuthError,