@pafi-dev/issuer 0.5.8 → 0.5.10
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 +174 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +132 -1
- package/dist/index.d.ts +132 -1
- package/dist/index.js +176 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1599,7 +1599,138 @@ interface IssuerService {
|
|
|
1599
1599
|
*/
|
|
1600
1600
|
declare function createIssuerService(config: IssuerServiceConfig): IssuerService;
|
|
1601
1601
|
|
|
1602
|
+
/**
|
|
1603
|
+
* A pending UserOp serialized for persistent storage (Redis, Postgres, memory).
|
|
1604
|
+
*
|
|
1605
|
+
* All bigint fields are stored as decimal strings so the entry can be
|
|
1606
|
+
* JSON-serialized without precision loss. Convert back to bigint before
|
|
1607
|
+
* calling `computeUserOpHash` or `serializeUserOpToJsonRpc`.
|
|
1608
|
+
*/
|
|
1609
|
+
interface PendingUserOpEntry {
|
|
1610
|
+
sender: Address;
|
|
1611
|
+
nonce: string;
|
|
1612
|
+
callData: Hex;
|
|
1613
|
+
callGasLimit: string;
|
|
1614
|
+
verificationGasLimit: string;
|
|
1615
|
+
preVerificationGas: string;
|
|
1616
|
+
maxFeePerGas: string;
|
|
1617
|
+
maxPriorityFeePerGas: string;
|
|
1618
|
+
paymaster?: Address;
|
|
1619
|
+
paymasterVerificationGasLimit?: string;
|
|
1620
|
+
paymasterPostOpGasLimit?: string;
|
|
1621
|
+
paymasterData?: Hex;
|
|
1622
|
+
chainId: number;
|
|
1623
|
+
/** Hex-encoded userOpHash — the value the user signed via personal_sign. */
|
|
1624
|
+
userOpHash: Hex;
|
|
1625
|
+
}
|
|
1626
|
+
/**
|
|
1627
|
+
* Storage backend for pending UserOps in the mobile prepare/submit pattern.
|
|
1628
|
+
*
|
|
1629
|
+
* Implement this interface and wire it into your issuer backend:
|
|
1630
|
+
* - `save()` — called by `POST /claim/prepare` and `POST /redeem/prepare`
|
|
1631
|
+
* - `get()` — called by `POST /claim/submit` and `POST /redeem/submit`
|
|
1632
|
+
* - `delete()` — called after successful submit or explicit cancellation
|
|
1633
|
+
*
|
|
1634
|
+
* The default implementation in the gg56 boilerplate uses Redis with
|
|
1635
|
+
* a short TTL matching the MintRequest / BurnRequest deadline.
|
|
1636
|
+
*/
|
|
1637
|
+
interface IPendingUserOpStore {
|
|
1638
|
+
save(lockId: string, entry: PendingUserOpEntry, ttlSeconds: number): Promise<void>;
|
|
1639
|
+
get(lockId: string): Promise<PendingUserOpEntry | null>;
|
|
1640
|
+
delete(lockId: string): Promise<void>;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
interface IssuerRegistryRecord {
|
|
1644
|
+
issuerAddress: Address;
|
|
1645
|
+
signerAddress: Address;
|
|
1646
|
+
name: string;
|
|
1647
|
+
symbol: string;
|
|
1648
|
+
declaredTotalSupply: bigint;
|
|
1649
|
+
capBasisPoints: number;
|
|
1650
|
+
active: boolean;
|
|
1651
|
+
pointToken: Address;
|
|
1652
|
+
mintingOracle: Address;
|
|
1653
|
+
}
|
|
1654
|
+
interface PreValidateMintResult {
|
|
1655
|
+
/** Registry record read at pre-validation time. */
|
|
1656
|
+
issuer: IssuerRegistryRecord;
|
|
1657
|
+
/** Current on-chain PointToken.totalSupply(). */
|
|
1658
|
+
totalSupply: bigint;
|
|
1659
|
+
/** declaredTotalSupply × capBasisPoints / 10000. */
|
|
1660
|
+
hardCap: bigint;
|
|
1661
|
+
/** hardCap − totalSupply (clamped to 0). */
|
|
1662
|
+
remaining: bigint;
|
|
1663
|
+
}
|
|
1664
|
+
/**
|
|
1665
|
+
* Thrown by `IssuerStateValidator.preValidateMint()`.
|
|
1666
|
+
* `code` maps 1:1 to the HTTP error the issuer API surfaces to clients.
|
|
1667
|
+
*/
|
|
1668
|
+
declare class IssuerStateError extends Error {
|
|
1669
|
+
readonly code: "ISSUER_NOT_REGISTERED" | "ISSUER_INACTIVE" | "MINT_CAP_EXCEEDED";
|
|
1670
|
+
readonly details?: Record<string, unknown> | undefined;
|
|
1671
|
+
constructor(code: "ISSUER_NOT_REGISTERED" | "ISSUER_INACTIVE" | "MINT_CAP_EXCEEDED", message: string, details?: Record<string, unknown> | undefined);
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
/**
|
|
1675
|
+
* Pure (framework-agnostic) validator for issuer state.
|
|
1676
|
+
*
|
|
1677
|
+
* Reads IssuerRegistry + PointToken on-chain state and pre-validates
|
|
1678
|
+
* mint requests before the user submits a UserOp. Catching these
|
|
1679
|
+
* off-chain lets issuers fail fast with a clear error rather than
|
|
1680
|
+
* wasting gas on a revert.
|
|
1681
|
+
*
|
|
1682
|
+
* Caching:
|
|
1683
|
+
* - `PointToken.issuer()` — memoized for the process lifetime (immutable)
|
|
1684
|
+
* - Full state (registry + totalSupply) — 30s TTL per PointToken
|
|
1685
|
+
* - Burst calls while a fetch is in-flight share the same Promise
|
|
1686
|
+
* (thundering-herd protection)
|
|
1687
|
+
*
|
|
1688
|
+
* Usage in NestJS: wrap this in an `@Injectable()` service; pass
|
|
1689
|
+
* `PublicClient` and `registryAddress` from your DI container.
|
|
1690
|
+
*/
|
|
1691
|
+
declare class IssuerStateValidator {
|
|
1692
|
+
private readonly provider;
|
|
1693
|
+
private readonly registryAddress;
|
|
1694
|
+
private readonly pointTokenIssuerCache;
|
|
1695
|
+
private readonly stateCache;
|
|
1696
|
+
private readonly inflight;
|
|
1697
|
+
constructor(provider: PublicClient, registryAddress: Address);
|
|
1698
|
+
/**
|
|
1699
|
+
* Convenience factory — reads `registryAddress` from the SDK
|
|
1700
|
+
* `CONTRACT_ADDRESSES` map for the given chain.
|
|
1701
|
+
*/
|
|
1702
|
+
static forChain(provider: PublicClient, chainId: number): IssuerStateValidator;
|
|
1703
|
+
/**
|
|
1704
|
+
* Invalidate cached state for one PointToken, or everything if omitted.
|
|
1705
|
+
* Call after admin txs that change registry or cap settings.
|
|
1706
|
+
*/
|
|
1707
|
+
invalidate(pointToken?: Address): void;
|
|
1708
|
+
/**
|
|
1709
|
+
* Resolve `PointToken.issuer()` once per token and memoize.
|
|
1710
|
+
* The issuer field is set at `initialize()` and never changes.
|
|
1711
|
+
*/
|
|
1712
|
+
getIssuerAddressForPointToken(pointToken: Address): Promise<Address>;
|
|
1713
|
+
/**
|
|
1714
|
+
* Read registry record + totalSupply, with 30s cache and in-flight
|
|
1715
|
+
* deduplication. Does NOT throw on inactive/missing — returns raw state.
|
|
1716
|
+
*/
|
|
1717
|
+
getIssuerState(pointToken: Address): Promise<PreValidateMintResult>;
|
|
1718
|
+
/**
|
|
1719
|
+
* Validate that `amount` PT can be minted on `pointToken` right now.
|
|
1720
|
+
*
|
|
1721
|
+
* Throws `IssuerStateError` with:
|
|
1722
|
+
* - `ISSUER_NOT_REGISTERED` — registry has no record for this issuer
|
|
1723
|
+
* - `ISSUER_INACTIVE` — issuer.active is false
|
|
1724
|
+
* - `MINT_CAP_EXCEEDED` — totalSupply + amount would exceed hardCap
|
|
1725
|
+
*
|
|
1726
|
+
* Returns the fetched state on success so callers can log without a
|
|
1727
|
+
* second RPC round-trip.
|
|
1728
|
+
*/
|
|
1729
|
+
preValidateMint(pointToken: Address, amount: bigint): Promise<PreValidateMintResult>;
|
|
1730
|
+
private fetchIssuerState;
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1602
1733
|
/** SDK package version — bumped on every release */
|
|
1603
1734
|
declare const PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
1604
1735
|
|
|
1605
|
-
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 IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerService, type IssuerServiceConfig, 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, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, 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 };
|
|
1736
|
+
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -1599,7 +1599,138 @@ interface IssuerService {
|
|
|
1599
1599
|
*/
|
|
1600
1600
|
declare function createIssuerService(config: IssuerServiceConfig): IssuerService;
|
|
1601
1601
|
|
|
1602
|
+
/**
|
|
1603
|
+
* A pending UserOp serialized for persistent storage (Redis, Postgres, memory).
|
|
1604
|
+
*
|
|
1605
|
+
* All bigint fields are stored as decimal strings so the entry can be
|
|
1606
|
+
* JSON-serialized without precision loss. Convert back to bigint before
|
|
1607
|
+
* calling `computeUserOpHash` or `serializeUserOpToJsonRpc`.
|
|
1608
|
+
*/
|
|
1609
|
+
interface PendingUserOpEntry {
|
|
1610
|
+
sender: Address;
|
|
1611
|
+
nonce: string;
|
|
1612
|
+
callData: Hex;
|
|
1613
|
+
callGasLimit: string;
|
|
1614
|
+
verificationGasLimit: string;
|
|
1615
|
+
preVerificationGas: string;
|
|
1616
|
+
maxFeePerGas: string;
|
|
1617
|
+
maxPriorityFeePerGas: string;
|
|
1618
|
+
paymaster?: Address;
|
|
1619
|
+
paymasterVerificationGasLimit?: string;
|
|
1620
|
+
paymasterPostOpGasLimit?: string;
|
|
1621
|
+
paymasterData?: Hex;
|
|
1622
|
+
chainId: number;
|
|
1623
|
+
/** Hex-encoded userOpHash — the value the user signed via personal_sign. */
|
|
1624
|
+
userOpHash: Hex;
|
|
1625
|
+
}
|
|
1626
|
+
/**
|
|
1627
|
+
* Storage backend for pending UserOps in the mobile prepare/submit pattern.
|
|
1628
|
+
*
|
|
1629
|
+
* Implement this interface and wire it into your issuer backend:
|
|
1630
|
+
* - `save()` — called by `POST /claim/prepare` and `POST /redeem/prepare`
|
|
1631
|
+
* - `get()` — called by `POST /claim/submit` and `POST /redeem/submit`
|
|
1632
|
+
* - `delete()` — called after successful submit or explicit cancellation
|
|
1633
|
+
*
|
|
1634
|
+
* The default implementation in the gg56 boilerplate uses Redis with
|
|
1635
|
+
* a short TTL matching the MintRequest / BurnRequest deadline.
|
|
1636
|
+
*/
|
|
1637
|
+
interface IPendingUserOpStore {
|
|
1638
|
+
save(lockId: string, entry: PendingUserOpEntry, ttlSeconds: number): Promise<void>;
|
|
1639
|
+
get(lockId: string): Promise<PendingUserOpEntry | null>;
|
|
1640
|
+
delete(lockId: string): Promise<void>;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
interface IssuerRegistryRecord {
|
|
1644
|
+
issuerAddress: Address;
|
|
1645
|
+
signerAddress: Address;
|
|
1646
|
+
name: string;
|
|
1647
|
+
symbol: string;
|
|
1648
|
+
declaredTotalSupply: bigint;
|
|
1649
|
+
capBasisPoints: number;
|
|
1650
|
+
active: boolean;
|
|
1651
|
+
pointToken: Address;
|
|
1652
|
+
mintingOracle: Address;
|
|
1653
|
+
}
|
|
1654
|
+
interface PreValidateMintResult {
|
|
1655
|
+
/** Registry record read at pre-validation time. */
|
|
1656
|
+
issuer: IssuerRegistryRecord;
|
|
1657
|
+
/** Current on-chain PointToken.totalSupply(). */
|
|
1658
|
+
totalSupply: bigint;
|
|
1659
|
+
/** declaredTotalSupply × capBasisPoints / 10000. */
|
|
1660
|
+
hardCap: bigint;
|
|
1661
|
+
/** hardCap − totalSupply (clamped to 0). */
|
|
1662
|
+
remaining: bigint;
|
|
1663
|
+
}
|
|
1664
|
+
/**
|
|
1665
|
+
* Thrown by `IssuerStateValidator.preValidateMint()`.
|
|
1666
|
+
* `code` maps 1:1 to the HTTP error the issuer API surfaces to clients.
|
|
1667
|
+
*/
|
|
1668
|
+
declare class IssuerStateError extends Error {
|
|
1669
|
+
readonly code: "ISSUER_NOT_REGISTERED" | "ISSUER_INACTIVE" | "MINT_CAP_EXCEEDED";
|
|
1670
|
+
readonly details?: Record<string, unknown> | undefined;
|
|
1671
|
+
constructor(code: "ISSUER_NOT_REGISTERED" | "ISSUER_INACTIVE" | "MINT_CAP_EXCEEDED", message: string, details?: Record<string, unknown> | undefined);
|
|
1672
|
+
}
|
|
1673
|
+
|
|
1674
|
+
/**
|
|
1675
|
+
* Pure (framework-agnostic) validator for issuer state.
|
|
1676
|
+
*
|
|
1677
|
+
* Reads IssuerRegistry + PointToken on-chain state and pre-validates
|
|
1678
|
+
* mint requests before the user submits a UserOp. Catching these
|
|
1679
|
+
* off-chain lets issuers fail fast with a clear error rather than
|
|
1680
|
+
* wasting gas on a revert.
|
|
1681
|
+
*
|
|
1682
|
+
* Caching:
|
|
1683
|
+
* - `PointToken.issuer()` — memoized for the process lifetime (immutable)
|
|
1684
|
+
* - Full state (registry + totalSupply) — 30s TTL per PointToken
|
|
1685
|
+
* - Burst calls while a fetch is in-flight share the same Promise
|
|
1686
|
+
* (thundering-herd protection)
|
|
1687
|
+
*
|
|
1688
|
+
* Usage in NestJS: wrap this in an `@Injectable()` service; pass
|
|
1689
|
+
* `PublicClient` and `registryAddress` from your DI container.
|
|
1690
|
+
*/
|
|
1691
|
+
declare class IssuerStateValidator {
|
|
1692
|
+
private readonly provider;
|
|
1693
|
+
private readonly registryAddress;
|
|
1694
|
+
private readonly pointTokenIssuerCache;
|
|
1695
|
+
private readonly stateCache;
|
|
1696
|
+
private readonly inflight;
|
|
1697
|
+
constructor(provider: PublicClient, registryAddress: Address);
|
|
1698
|
+
/**
|
|
1699
|
+
* Convenience factory — reads `registryAddress` from the SDK
|
|
1700
|
+
* `CONTRACT_ADDRESSES` map for the given chain.
|
|
1701
|
+
*/
|
|
1702
|
+
static forChain(provider: PublicClient, chainId: number): IssuerStateValidator;
|
|
1703
|
+
/**
|
|
1704
|
+
* Invalidate cached state for one PointToken, or everything if omitted.
|
|
1705
|
+
* Call after admin txs that change registry or cap settings.
|
|
1706
|
+
*/
|
|
1707
|
+
invalidate(pointToken?: Address): void;
|
|
1708
|
+
/**
|
|
1709
|
+
* Resolve `PointToken.issuer()` once per token and memoize.
|
|
1710
|
+
* The issuer field is set at `initialize()` and never changes.
|
|
1711
|
+
*/
|
|
1712
|
+
getIssuerAddressForPointToken(pointToken: Address): Promise<Address>;
|
|
1713
|
+
/**
|
|
1714
|
+
* Read registry record + totalSupply, with 30s cache and in-flight
|
|
1715
|
+
* deduplication. Does NOT throw on inactive/missing — returns raw state.
|
|
1716
|
+
*/
|
|
1717
|
+
getIssuerState(pointToken: Address): Promise<PreValidateMintResult>;
|
|
1718
|
+
/**
|
|
1719
|
+
* Validate that `amount` PT can be minted on `pointToken` right now.
|
|
1720
|
+
*
|
|
1721
|
+
* Throws `IssuerStateError` with:
|
|
1722
|
+
* - `ISSUER_NOT_REGISTERED` — registry has no record for this issuer
|
|
1723
|
+
* - `ISSUER_INACTIVE` — issuer.active is false
|
|
1724
|
+
* - `MINT_CAP_EXCEEDED` — totalSupply + amount would exceed hardCap
|
|
1725
|
+
*
|
|
1726
|
+
* Returns the fetched state on success so callers can log without a
|
|
1727
|
+
* second RPC round-trip.
|
|
1728
|
+
*/
|
|
1729
|
+
preValidateMint(pointToken: Address, amount: bigint): Promise<PreValidateMintResult>;
|
|
1730
|
+
private fetchIssuerState;
|
|
1731
|
+
}
|
|
1732
|
+
|
|
1602
1733
|
/** SDK package version — bumped on every release */
|
|
1603
1734
|
declare const PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
1604
1735
|
|
|
1605
|
-
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 IPointLedger, type IPolicyEngine, type ISessionStore, InMemoryCursorStore, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerService, type IssuerServiceConfig, 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, PointIndexer, type PointIndexerConfig, type PolicyDecision, type PolicyEvalRequest, type PoolsProvider, 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 };
|
|
1736
|
+
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 };
|
package/dist/index.js
CHANGED
|
@@ -2056,6 +2056,180 @@ function createIssuerService(config) {
|
|
|
2056
2056
|
};
|
|
2057
2057
|
}
|
|
2058
2058
|
|
|
2059
|
+
// src/issuer-state/validator.ts
|
|
2060
|
+
import { getAddress as getAddress9 } from "viem";
|
|
2061
|
+
import {
|
|
2062
|
+
POINT_TOKEN_V2_ABI as POINT_TOKEN_V2_ABI3,
|
|
2063
|
+
issuerRegistryAbi,
|
|
2064
|
+
getContractAddresses as getContractAddresses2
|
|
2065
|
+
} from "@pafi-dev/core";
|
|
2066
|
+
|
|
2067
|
+
// src/issuer-state/types.ts
|
|
2068
|
+
var IssuerStateError = class extends Error {
|
|
2069
|
+
constructor(code, message, details) {
|
|
2070
|
+
super(message);
|
|
2071
|
+
this.code = code;
|
|
2072
|
+
this.details = details;
|
|
2073
|
+
this.name = "IssuerStateError";
|
|
2074
|
+
}
|
|
2075
|
+
code;
|
|
2076
|
+
details;
|
|
2077
|
+
};
|
|
2078
|
+
|
|
2079
|
+
// src/issuer-state/validator.ts
|
|
2080
|
+
var ISSUER_RECORD_TTL_MS = 3e4;
|
|
2081
|
+
var IssuerStateValidator = class _IssuerStateValidator {
|
|
2082
|
+
constructor(provider, registryAddress) {
|
|
2083
|
+
this.provider = provider;
|
|
2084
|
+
this.registryAddress = registryAddress;
|
|
2085
|
+
}
|
|
2086
|
+
provider;
|
|
2087
|
+
registryAddress;
|
|
2088
|
+
pointTokenIssuerCache = /* @__PURE__ */ new Map();
|
|
2089
|
+
stateCache = /* @__PURE__ */ new Map();
|
|
2090
|
+
inflight = /* @__PURE__ */ new Map();
|
|
2091
|
+
/**
|
|
2092
|
+
* Convenience factory — reads `registryAddress` from the SDK
|
|
2093
|
+
* `CONTRACT_ADDRESSES` map for the given chain.
|
|
2094
|
+
*/
|
|
2095
|
+
static forChain(provider, chainId) {
|
|
2096
|
+
const { issuerRegistry } = getContractAddresses2(chainId);
|
|
2097
|
+
return new _IssuerStateValidator(provider, issuerRegistry);
|
|
2098
|
+
}
|
|
2099
|
+
/**
|
|
2100
|
+
* Invalidate cached state for one PointToken, or everything if omitted.
|
|
2101
|
+
* Call after admin txs that change registry or cap settings.
|
|
2102
|
+
*/
|
|
2103
|
+
invalidate(pointToken) {
|
|
2104
|
+
if (pointToken) {
|
|
2105
|
+
const key = getAddress9(pointToken);
|
|
2106
|
+
this.pointTokenIssuerCache.delete(key);
|
|
2107
|
+
this.stateCache.delete(key);
|
|
2108
|
+
this.inflight.delete(key);
|
|
2109
|
+
} else {
|
|
2110
|
+
this.pointTokenIssuerCache.clear();
|
|
2111
|
+
this.stateCache.clear();
|
|
2112
|
+
this.inflight.clear();
|
|
2113
|
+
}
|
|
2114
|
+
}
|
|
2115
|
+
/**
|
|
2116
|
+
* Resolve `PointToken.issuer()` once per token and memoize.
|
|
2117
|
+
* The issuer field is set at `initialize()` and never changes.
|
|
2118
|
+
*/
|
|
2119
|
+
async getIssuerAddressForPointToken(pointToken) {
|
|
2120
|
+
const key = getAddress9(pointToken);
|
|
2121
|
+
const cached = this.pointTokenIssuerCache.get(key);
|
|
2122
|
+
if (cached) return cached;
|
|
2123
|
+
const issuer = await this.provider.readContract({
|
|
2124
|
+
address: key,
|
|
2125
|
+
abi: POINT_TOKEN_V2_ABI3,
|
|
2126
|
+
functionName: "issuer"
|
|
2127
|
+
});
|
|
2128
|
+
this.pointTokenIssuerCache.set(key, getAddress9(issuer));
|
|
2129
|
+
return getAddress9(issuer);
|
|
2130
|
+
}
|
|
2131
|
+
/**
|
|
2132
|
+
* Read registry record + totalSupply, with 30s cache and in-flight
|
|
2133
|
+
* deduplication. Does NOT throw on inactive/missing — returns raw state.
|
|
2134
|
+
*/
|
|
2135
|
+
async getIssuerState(pointToken) {
|
|
2136
|
+
const tokenAddr = getAddress9(pointToken);
|
|
2137
|
+
const now = Date.now();
|
|
2138
|
+
const cached = this.stateCache.get(tokenAddr);
|
|
2139
|
+
if (cached && cached.expiresAt > now) return cached.value;
|
|
2140
|
+
const existing = this.inflight.get(tokenAddr);
|
|
2141
|
+
if (existing) return existing;
|
|
2142
|
+
const promise = this.fetchIssuerState(tokenAddr).then((state) => {
|
|
2143
|
+
this.stateCache.set(tokenAddr, {
|
|
2144
|
+
value: state,
|
|
2145
|
+
expiresAt: Date.now() + ISSUER_RECORD_TTL_MS
|
|
2146
|
+
});
|
|
2147
|
+
return state;
|
|
2148
|
+
}).finally(() => {
|
|
2149
|
+
this.inflight.delete(tokenAddr);
|
|
2150
|
+
});
|
|
2151
|
+
this.inflight.set(tokenAddr, promise);
|
|
2152
|
+
return promise;
|
|
2153
|
+
}
|
|
2154
|
+
/**
|
|
2155
|
+
* Validate that `amount` PT can be minted on `pointToken` right now.
|
|
2156
|
+
*
|
|
2157
|
+
* Throws `IssuerStateError` with:
|
|
2158
|
+
* - `ISSUER_NOT_REGISTERED` — registry has no record for this issuer
|
|
2159
|
+
* - `ISSUER_INACTIVE` — issuer.active is false
|
|
2160
|
+
* - `MINT_CAP_EXCEEDED` — totalSupply + amount would exceed hardCap
|
|
2161
|
+
*
|
|
2162
|
+
* Returns the fetched state on success so callers can log without a
|
|
2163
|
+
* second RPC round-trip.
|
|
2164
|
+
*/
|
|
2165
|
+
async preValidateMint(pointToken, amount) {
|
|
2166
|
+
let state;
|
|
2167
|
+
try {
|
|
2168
|
+
state = await this.getIssuerState(pointToken);
|
|
2169
|
+
} catch (err) {
|
|
2170
|
+
if (err.message.includes("IssuerNotFound")) {
|
|
2171
|
+
throw new IssuerStateError(
|
|
2172
|
+
"ISSUER_NOT_REGISTERED",
|
|
2173
|
+
`IssuerRegistry has no record for PointToken ${pointToken}`,
|
|
2174
|
+
{ pointToken }
|
|
2175
|
+
);
|
|
2176
|
+
}
|
|
2177
|
+
throw err;
|
|
2178
|
+
}
|
|
2179
|
+
const { issuer, totalSupply, hardCap, remaining } = state;
|
|
2180
|
+
if (!issuer.active) {
|
|
2181
|
+
throw new IssuerStateError(
|
|
2182
|
+
"ISSUER_INACTIVE",
|
|
2183
|
+
`Issuer ${issuer.issuerAddress} is deactivated on IssuerRegistry`,
|
|
2184
|
+
{ issuer: issuer.issuerAddress, pointToken: issuer.pointToken }
|
|
2185
|
+
);
|
|
2186
|
+
}
|
|
2187
|
+
if (totalSupply + amount > hardCap) {
|
|
2188
|
+
throw new IssuerStateError(
|
|
2189
|
+
"MINT_CAP_EXCEEDED",
|
|
2190
|
+
`Requested ${amount} PT would exceed mint cap. Cap=${hardCap}, minted=${totalSupply}, remaining=${remaining}`,
|
|
2191
|
+
{
|
|
2192
|
+
requested: amount.toString(),
|
|
2193
|
+
cap: hardCap.toString(),
|
|
2194
|
+
minted: totalSupply.toString(),
|
|
2195
|
+
remaining: remaining.toString()
|
|
2196
|
+
}
|
|
2197
|
+
);
|
|
2198
|
+
}
|
|
2199
|
+
return state;
|
|
2200
|
+
}
|
|
2201
|
+
async fetchIssuerState(tokenAddr) {
|
|
2202
|
+
const issuerAddr = await this.getIssuerAddressForPointToken(tokenAddr);
|
|
2203
|
+
const [tuple, totalSupply] = await Promise.all([
|
|
2204
|
+
this.provider.readContract({
|
|
2205
|
+
address: this.registryAddress,
|
|
2206
|
+
abi: issuerRegistryAbi,
|
|
2207
|
+
functionName: "getIssuer",
|
|
2208
|
+
args: [issuerAddr]
|
|
2209
|
+
}),
|
|
2210
|
+
this.provider.readContract({
|
|
2211
|
+
address: tokenAddr,
|
|
2212
|
+
abi: POINT_TOKEN_V2_ABI3,
|
|
2213
|
+
functionName: "totalSupply"
|
|
2214
|
+
})
|
|
2215
|
+
]);
|
|
2216
|
+
const issuer = {
|
|
2217
|
+
issuerAddress: tuple[0],
|
|
2218
|
+
signerAddress: tuple[1],
|
|
2219
|
+
name: tuple[2],
|
|
2220
|
+
symbol: tuple[3],
|
|
2221
|
+
declaredTotalSupply: tuple[4],
|
|
2222
|
+
capBasisPoints: tuple[5],
|
|
2223
|
+
active: tuple[6],
|
|
2224
|
+
pointToken: tuple[7],
|
|
2225
|
+
mintingOracle: tuple[8]
|
|
2226
|
+
};
|
|
2227
|
+
const hardCap = issuer.declaredTotalSupply * BigInt(issuer.capBasisPoints) / 10000n;
|
|
2228
|
+
const remaining = hardCap > totalSupply ? hardCap - totalSupply : 0n;
|
|
2229
|
+
return { issuer, totalSupply, hardCap, remaining };
|
|
2230
|
+
}
|
|
2231
|
+
};
|
|
2232
|
+
|
|
2059
2233
|
// src/index.ts
|
|
2060
2234
|
var PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
2061
2235
|
export {
|
|
@@ -2067,6 +2241,8 @@ export {
|
|
|
2067
2241
|
FeeManager,
|
|
2068
2242
|
InMemoryCursorStore,
|
|
2069
2243
|
IssuerApiHandlers,
|
|
2244
|
+
IssuerStateError,
|
|
2245
|
+
IssuerStateValidator,
|
|
2070
2246
|
MemorySessionStore,
|
|
2071
2247
|
NonceManager,
|
|
2072
2248
|
PAFI_ISSUER_SDK_VERSION,
|