@pafi-dev/issuer 0.5.11 → 0.5.12

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
@@ -1354,6 +1354,48 @@ interface SubgraphNativeUsdtQuoterConfig {
1354
1354
  */
1355
1355
  declare function createSubgraphNativeUsdtQuoter(config?: SubgraphNativeUsdtQuoterConfig): (amountNative: bigint) => Promise<bigint>;
1356
1356
 
1357
+ interface NativePtQuoterConfig {
1358
+ /** Viem PublicClient — used to call Chainlink on-chain. */
1359
+ provider: PublicClient;
1360
+ /** Address of the PointToken being traded. */
1361
+ pointTokenAddress: Address;
1362
+ /** Chainlink ETH/USD feed address. Defaults to Base mainnet feed. */
1363
+ chainlinkFeedAddress?: Address;
1364
+ /** PAFI subgraph GraphQL endpoint. */
1365
+ subgraphUrl?: string;
1366
+ /** Cache TTL in ms. Default: 30_000. */
1367
+ cacheTtlMs?: number;
1368
+ /** Fallback ETH price (USD) when Chainlink is unreachable. Default: 3000. */
1369
+ fallbackEthPriceUsd?: number;
1370
+ /** Fallback PT price (USDT per 1 PT) when subgraph is unreachable. Default: 0.1. */
1371
+ fallbackPtPriceUsdt?: number;
1372
+ fetchImpl?: typeof fetch;
1373
+ now?: () => number;
1374
+ }
1375
+ /**
1376
+ * Create a native→PT quoter for use as `FeeManager.quoteNativeToFee`.
1377
+ *
1378
+ * Converts ETH gas cost → USDT (via Chainlink ETH/USD) → PT (via subgraph
1379
+ * pool price), returning the fee amount in PT raw units (18 decimals).
1380
+ *
1381
+ * Formula:
1382
+ * feeInPT = amountNative × ethPrice_8dec × ptPerUsdt_18dec / 10^26
1383
+ *
1384
+ * Both prices are cached in-process (default 30s TTL).
1385
+ *
1386
+ * @example
1387
+ * ```ts
1388
+ * fee: {
1389
+ * quoteNativeToFee: createNativePtQuoter({
1390
+ * provider,
1391
+ * pointTokenAddress: "0x...",
1392
+ * chainlinkFeedAddress: getContractAddresses(chainId).chainlinkEthUsd,
1393
+ * }),
1394
+ * }
1395
+ * ```
1396
+ */
1397
+ declare function createNativePtQuoter(config: NativePtQuoterConfig): (amountNative: bigint) => Promise<bigint>;
1398
+
1357
1399
  /**
1358
1400
  * Combined off-chain + on-chain balance for a single user / token pair.
1359
1401
  *
@@ -1742,4 +1784,4 @@ declare class IssuerStateValidator {
1742
1784
  /** SDK package version — bumped on every release */
1743
1785
  declare const PAFI_ISSUER_SDK_VERSION = "0.4.0";
1744
1786
 
1745
- export { type ApiClaimRequest, type ApiClaimResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedeemRequest, type ApiRedeemResponse, type ApiTopUpRequest, type ApiTopUpResponse, 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 IPendingUserOpStore, type IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerRegistryRecord, type IssuerService, type IssuerServiceConfig, IssuerStateError, IssuerStateValidator, type LockedMintRequest, type LoginResult, MemorySessionStore, type MemorySessionStoreOptions, type MintEvent, type MintingStatus, NonceManager, PAFI_ISSUER_SDK_VERSION, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, type PendingUserOpEntry, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, type PreValidateMintResult, type PrepareBurnDirectParams, type PrepareBurnParams, type PrepareBurnWithSigParams, type PrepareMintParams, RelayError, type RelayErrorCode, RelayService, type RelayUserOpRequest, type RelayUserOpResponse, type RetryConfig, type Session, type SponsorshipRequest, type SponsorshipResponse, type SponsorshipTarget, type SponsorshipUserOp, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, TopUpRedemptionError, TopUpRedemptionHandler, type TopUpRedemptionHandlerConfig, type TopUpRedemptionRequest, type TopUpRedemptionResponse, authenticateRequest, createIssuerService, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, serializeEntryToJsonRpc };
1787
+ export { type ApiClaimRequest, type ApiClaimResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedeemRequest, type ApiRedeemResponse, type ApiTopUpRequest, type ApiTopUpResponse, 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 IPendingUserOpStore, type IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerRegistryRecord, type IssuerService, type IssuerServiceConfig, IssuerStateError, IssuerStateValidator, type LockedMintRequest, type LoginResult, MemorySessionStore, type MemorySessionStoreOptions, type MintEvent, type MintingStatus, type NativePtQuoterConfig, NonceManager, PAFI_ISSUER_SDK_VERSION, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, type PendingUserOpEntry, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, type PreValidateMintResult, type PrepareBurnDirectParams, type PrepareBurnParams, type PrepareBurnWithSigParams, type PrepareMintParams, RelayError, type RelayErrorCode, RelayService, type RelayUserOpRequest, type RelayUserOpResponse, type RetryConfig, type Session, type SponsorshipRequest, type SponsorshipResponse, type SponsorshipTarget, type SponsorshipUserOp, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, TopUpRedemptionError, TopUpRedemptionHandler, type TopUpRedemptionHandlerConfig, type TopUpRedemptionRequest, type TopUpRedemptionResponse, authenticateRequest, createIssuerService, createNativePtQuoter, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, serializeEntryToJsonRpc };
package/dist/index.d.ts CHANGED
@@ -1354,6 +1354,48 @@ interface SubgraphNativeUsdtQuoterConfig {
1354
1354
  */
1355
1355
  declare function createSubgraphNativeUsdtQuoter(config?: SubgraphNativeUsdtQuoterConfig): (amountNative: bigint) => Promise<bigint>;
1356
1356
 
1357
+ interface NativePtQuoterConfig {
1358
+ /** Viem PublicClient — used to call Chainlink on-chain. */
1359
+ provider: PublicClient;
1360
+ /** Address of the PointToken being traded. */
1361
+ pointTokenAddress: Address;
1362
+ /** Chainlink ETH/USD feed address. Defaults to Base mainnet feed. */
1363
+ chainlinkFeedAddress?: Address;
1364
+ /** PAFI subgraph GraphQL endpoint. */
1365
+ subgraphUrl?: string;
1366
+ /** Cache TTL in ms. Default: 30_000. */
1367
+ cacheTtlMs?: number;
1368
+ /** Fallback ETH price (USD) when Chainlink is unreachable. Default: 3000. */
1369
+ fallbackEthPriceUsd?: number;
1370
+ /** Fallback PT price (USDT per 1 PT) when subgraph is unreachable. Default: 0.1. */
1371
+ fallbackPtPriceUsdt?: number;
1372
+ fetchImpl?: typeof fetch;
1373
+ now?: () => number;
1374
+ }
1375
+ /**
1376
+ * Create a native→PT quoter for use as `FeeManager.quoteNativeToFee`.
1377
+ *
1378
+ * Converts ETH gas cost → USDT (via Chainlink ETH/USD) → PT (via subgraph
1379
+ * pool price), returning the fee amount in PT raw units (18 decimals).
1380
+ *
1381
+ * Formula:
1382
+ * feeInPT = amountNative × ethPrice_8dec × ptPerUsdt_18dec / 10^26
1383
+ *
1384
+ * Both prices are cached in-process (default 30s TTL).
1385
+ *
1386
+ * @example
1387
+ * ```ts
1388
+ * fee: {
1389
+ * quoteNativeToFee: createNativePtQuoter({
1390
+ * provider,
1391
+ * pointTokenAddress: "0x...",
1392
+ * chainlinkFeedAddress: getContractAddresses(chainId).chainlinkEthUsd,
1393
+ * }),
1394
+ * }
1395
+ * ```
1396
+ */
1397
+ declare function createNativePtQuoter(config: NativePtQuoterConfig): (amountNative: bigint) => Promise<bigint>;
1398
+
1357
1399
  /**
1358
1400
  * Combined off-chain + on-chain balance for a single user / token pair.
1359
1401
  *
@@ -1742,4 +1784,4 @@ declare class IssuerStateValidator {
1742
1784
  /** SDK package version — bumped on every release */
1743
1785
  declare const PAFI_ISSUER_SDK_VERSION = "0.4.0";
1744
1786
 
1745
- export { type ApiClaimRequest, type ApiClaimResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedeemRequest, type ApiRedeemResponse, type ApiTopUpRequest, type ApiTopUpResponse, 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 IPendingUserOpStore, type IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerRegistryRecord, type IssuerService, type IssuerServiceConfig, IssuerStateError, IssuerStateValidator, type LockedMintRequest, type LoginResult, MemorySessionStore, type MemorySessionStoreOptions, type MintEvent, type MintingStatus, NonceManager, PAFI_ISSUER_SDK_VERSION, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, type PendingUserOpEntry, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, type PreValidateMintResult, type PrepareBurnDirectParams, type PrepareBurnParams, type PrepareBurnWithSigParams, type PrepareMintParams, RelayError, type RelayErrorCode, RelayService, type RelayUserOpRequest, type RelayUserOpResponse, type RetryConfig, type Session, type SponsorshipRequest, type SponsorshipResponse, type SponsorshipTarget, type SponsorshipUserOp, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, TopUpRedemptionError, TopUpRedemptionHandler, type TopUpRedemptionHandlerConfig, type TopUpRedemptionRequest, type TopUpRedemptionResponse, authenticateRequest, createIssuerService, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, serializeEntryToJsonRpc };
1787
+ export { type ApiClaimRequest, type ApiClaimResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedeemRequest, type ApiRedeemResponse, type ApiTopUpRequest, type ApiTopUpResponse, 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 IPendingUserOpStore, type IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerRegistryRecord, type IssuerService, type IssuerServiceConfig, IssuerStateError, IssuerStateValidator, type LockedMintRequest, type LoginResult, MemorySessionStore, type MemorySessionStoreOptions, type MintEvent, type MintingStatus, type NativePtQuoterConfig, NonceManager, PAFI_ISSUER_SDK_VERSION, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, type PendingUserOpEntry, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, type PreValidateMintResult, type PrepareBurnDirectParams, type PrepareBurnParams, type PrepareBurnWithSigParams, type PrepareMintParams, RelayError, type RelayErrorCode, RelayService, type RelayUserOpRequest, type RelayUserOpResponse, type RetryConfig, type Session, type SponsorshipRequest, type SponsorshipResponse, type SponsorshipTarget, type SponsorshipUserOp, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, TopUpRedemptionError, TopUpRedemptionHandler, type TopUpRedemptionHandlerConfig, type TopUpRedemptionRequest, type TopUpRedemptionResponse, authenticateRequest, createIssuerService, createNativePtQuoter, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, serializeEntryToJsonRpc };
package/dist/index.js CHANGED
@@ -1736,6 +1736,107 @@ function toUsdtPerNative(priceFloat, usdtDecimals) {
1736
1736
  return BigInt(whole + padded);
1737
1737
  }
1738
1738
 
1739
+ // src/pools/nativePtQuoter.ts
1740
+ import { parseAbi } from "viem";
1741
+ var CHAINLINK_ABI = parseAbi([
1742
+ "function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)"
1743
+ ]);
1744
+ var CHAINLINK_MAX_AGE_S = 3600n;
1745
+ var POOL_PRICE_QUERY = `
1746
+ query GetPoolPrice($id: ID!) {
1747
+ pafiToken(id: $id) {
1748
+ pool {
1749
+ token0 { id }
1750
+ token1 { id }
1751
+ token0Price
1752
+ token1Price
1753
+ }
1754
+ }
1755
+ }
1756
+ `;
1757
+ function createNativePtQuoter(config) {
1758
+ const {
1759
+ provider,
1760
+ pointTokenAddress,
1761
+ chainlinkFeedAddress = "0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70",
1762
+ subgraphUrl = PAFI_SUBGRAPH_URL,
1763
+ cacheTtlMs = 3e4,
1764
+ fallbackEthPriceUsd = 3e3,
1765
+ fallbackPtPriceUsdt = 0.1,
1766
+ fetchImpl = globalThis.fetch,
1767
+ now = () => Date.now()
1768
+ } = config;
1769
+ let ethPriceCache;
1770
+ let ptPriceCache;
1771
+ async function getEthPrice8dec() {
1772
+ const ts = now();
1773
+ if (ethPriceCache && ethPriceCache.expiresAt > ts) return ethPriceCache.value;
1774
+ try {
1775
+ const result = await provider.readContract({
1776
+ address: chainlinkFeedAddress,
1777
+ abi: CHAINLINK_ABI,
1778
+ functionName: "latestRoundData"
1779
+ });
1780
+ const answer = result[1];
1781
+ const updatedAt = result[3];
1782
+ if (answer <= 0n) throw new Error("Chainlink: non-positive price");
1783
+ const ageS = BigInt(Math.floor(ts / 1e3)) - updatedAt;
1784
+ if (ageS > CHAINLINK_MAX_AGE_S) {
1785
+ throw new Error(`Chainlink: price stale by ${ageS}s`);
1786
+ }
1787
+ ethPriceCache = { value: answer, expiresAt: ts + cacheTtlMs };
1788
+ return answer;
1789
+ } catch (err) {
1790
+ console.warn("[nativePtQuoter] Chainlink unavailable, using fallback:", err.message);
1791
+ return BigInt(Math.round(fallbackEthPriceUsd * 1e8));
1792
+ }
1793
+ }
1794
+ async function getPtPerUsdt18dec() {
1795
+ const ts = now();
1796
+ if (ptPriceCache && ptPriceCache.expiresAt > ts) return ptPriceCache.value;
1797
+ try {
1798
+ const response = await fetchImpl(subgraphUrl, {
1799
+ method: "POST",
1800
+ headers: { "Content-Type": "application/json" },
1801
+ body: JSON.stringify({
1802
+ query: POOL_PRICE_QUERY,
1803
+ variables: { id: pointTokenAddress.toLowerCase() }
1804
+ })
1805
+ });
1806
+ if (!response.ok) throw new Error(`subgraph HTTP ${response.status}`);
1807
+ const json = await response.json();
1808
+ if (json.errors?.length) throw new Error(json.errors.map((e) => e.message).join("; "));
1809
+ const pool = json.data?.pafiToken?.pool;
1810
+ if (!pool) throw new Error("pafiToken or pool not found in subgraph");
1811
+ const isPtToken0 = pool.token0.id.toLowerCase() === pointTokenAddress.toLowerCase();
1812
+ const ptPerUsdtStr = isPtToken0 ? pool.token0Price : pool.token1Price;
1813
+ if (!ptPerUsdtStr || Number(ptPerUsdtStr) <= 0) {
1814
+ throw new Error(`invalid PT/USDT price from subgraph: ${ptPerUsdtStr}`);
1815
+ }
1816
+ const value = parseBigDecimalTo18(ptPerUsdtStr);
1817
+ ptPriceCache = { value, expiresAt: ts + cacheTtlMs };
1818
+ return value;
1819
+ } catch (err) {
1820
+ console.warn("[nativePtQuoter] subgraph unavailable, using fallback:", err.message);
1821
+ return parseBigDecimalTo18(fallbackPtPriceUsdt.toString());
1822
+ }
1823
+ }
1824
+ return async (amountNative) => {
1825
+ if (amountNative === 0n) return 0n;
1826
+ const [ethPrice8dec, ptPerUsdt18dec] = await Promise.all([
1827
+ getEthPrice8dec(),
1828
+ getPtPerUsdt18dec()
1829
+ ]);
1830
+ return amountNative * ethPrice8dec * ptPerUsdt18dec / 10n ** 26n;
1831
+ };
1832
+ }
1833
+ function parseBigDecimalTo18(s) {
1834
+ const SCALE = 18;
1835
+ const [whole = "0", frac = ""] = s.split(".");
1836
+ const padded = (frac + "0".repeat(SCALE)).slice(0, SCALE);
1837
+ return BigInt(whole + padded);
1838
+ }
1839
+
1739
1840
  // src/balance/balanceAggregator.ts
1740
1841
  import { getPointTokenBalance as getPointTokenBalance4 } from "@pafi-dev/core";
1741
1842
  var BalanceAggregator = class {
@@ -2222,7 +2323,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
2222
2323
  }
2223
2324
  async fetchIssuerState(tokenAddr) {
2224
2325
  const issuerAddr = await this.getIssuerAddressForPointToken(tokenAddr);
2225
- const [tuple, totalSupply] = await Promise.all([
2326
+ const [issuerStruct, totalSupply] = await Promise.all([
2226
2327
  this.provider.readContract({
2227
2328
  address: this.registryAddress,
2228
2329
  abi: issuerRegistryAbi,
@@ -2235,17 +2336,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
2235
2336
  functionName: "totalSupply"
2236
2337
  })
2237
2338
  ]);
2238
- const issuer = {
2239
- issuerAddress: tuple[0],
2240
- signerAddress: tuple[1],
2241
- name: tuple[2],
2242
- symbol: tuple[3],
2243
- declaredTotalSupply: tuple[4],
2244
- capBasisPoints: tuple[5],
2245
- active: tuple[6],
2246
- pointToken: tuple[7],
2247
- mintingOracle: tuple[8]
2248
- };
2339
+ const issuer = issuerStruct;
2249
2340
  const hardCap = issuer.declaredTotalSupply * BigInt(issuer.capBasisPoints) / 10000n;
2250
2341
  const remaining = hardCap > totalSupply ? hardCap - totalSupply : 0n;
2251
2342
  return { issuer, totalSupply, hardCap, remaining };
@@ -2280,6 +2371,7 @@ export {
2280
2371
  TopUpRedemptionHandler,
2281
2372
  authenticateRequest,
2282
2373
  createIssuerService,
2374
+ createNativePtQuoter,
2283
2375
  createSubgraphNativeUsdtQuoter,
2284
2376
  createSubgraphPoolsProvider,
2285
2377
  serializeEntryToJsonRpc