@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.cjs +117 -40
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +109 -56
- package/dist/index.d.ts +109 -56
- package/dist/index.js +126 -49
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -967,12 +967,37 @@ interface BurnEvent {
|
|
|
967
967
|
* number it is about to process so the caller can write it to Redis /
|
|
968
968
|
* Postgres / a file. The SDK does not own persistence because every
|
|
969
969
|
* issuer has their own storage stack.
|
|
970
|
+
*
|
|
971
|
+
* **Per-token keying (audit finding H-05).** When multiple PointTokens
|
|
972
|
+
* are wired through a single `createIssuerService` call, each
|
|
973
|
+
* `PointIndexer` MUST get its own cursor — otherwise token A advances
|
|
974
|
+
* the shared cursor past token B's events and token B's mints are
|
|
975
|
+
* never finalized (off-chain balance never deducts → on-chain PT
|
|
976
|
+
* supply for token B exceeds off-chain backing). Combined with the
|
|
977
|
+
* H-04 monotonic-save fix this becomes a catastrophic-and-stable
|
|
978
|
+
* state where token B's cursor can never catch up. Implementations
|
|
979
|
+
* SHOULD expose `forKey(key)` returning a derived store keyed under
|
|
980
|
+
* a distinct namespace; the SDK factory calls it once per token.
|
|
981
|
+
*
|
|
982
|
+
* When `forKey` is absent, the SDK falls back to the bare store and
|
|
983
|
+
* emits a runtime warning if more than one token is configured. New
|
|
984
|
+
* implementations are strongly encouraged to add `forKey`.
|
|
970
985
|
*/
|
|
971
986
|
interface IIndexerCursorStore {
|
|
972
987
|
/** Return the last persisted cursor (`undefined` on first run). */
|
|
973
988
|
load(): Promise<bigint | undefined>;
|
|
974
989
|
/** Persist a new cursor value. Called after each successful batch. */
|
|
975
990
|
save(blockNumber: bigint): Promise<void>;
|
|
991
|
+
/**
|
|
992
|
+
* Return a derived store keyed under `key`. The returned store is
|
|
993
|
+
* an independent `IIndexerCursorStore` so the same persistence
|
|
994
|
+
* backend can serve N indexers with N distinct cursors.
|
|
995
|
+
*
|
|
996
|
+
* Optional for backwards compatibility, but REQUIRED in practice
|
|
997
|
+
* whenever more than one PointToken is wired through the SDK
|
|
998
|
+
* factory (see H-05).
|
|
999
|
+
*/
|
|
1000
|
+
forKey?(key: string): IIndexerCursorStore;
|
|
976
1001
|
}
|
|
977
1002
|
/**
|
|
978
1003
|
* No-op cursor store. Useful when the caller wants to drive the cursor
|
|
@@ -980,49 +1005,19 @@ interface IIndexerCursorStore {
|
|
|
980
1005
|
*/
|
|
981
1006
|
declare class InMemoryCursorStore implements IIndexerCursorStore {
|
|
982
1007
|
private cursor;
|
|
1008
|
+
/**
|
|
1009
|
+
* Child stores keyed by `forKey()`. Each child has its own cursor
|
|
1010
|
+
* (the H-05 fix), so a single InMemoryCursorStore can back N
|
|
1011
|
+
* PointIndexers in tests / single-process callers.
|
|
1012
|
+
*/
|
|
1013
|
+
private readonly children;
|
|
983
1014
|
load(): Promise<bigint | undefined>;
|
|
984
1015
|
save(blockNumber: bigint): Promise<void>;
|
|
1016
|
+
forKey(key: string): IIndexerCursorStore;
|
|
985
1017
|
}
|
|
986
|
-
/**
|
|
987
|
-
* Lock handle returned by a successful `ISingletonLock.acquire()`.
|
|
988
|
-
*
|
|
989
|
-
* The holder is the leader for the keyed indexer; non-holders MUST NOT
|
|
990
|
-
* call `indexer.start()` (else they race against the leader's polling
|
|
991
|
-
* loop and last-writer-wins cursor save corrupts replay state).
|
|
992
|
-
*
|
|
993
|
-
* `release()` is called by the leader on graceful shutdown. If the
|
|
994
|
-
* leader crashes without calling release, the lock implementation
|
|
995
|
-
* MUST drop the lock automatically (e.g. Postgres advisory locks
|
|
996
|
-
* auto-release on connection close).
|
|
997
|
-
*/
|
|
998
1018
|
interface SingletonLockHandle {
|
|
999
1019
|
release(): Promise<void>;
|
|
1000
1020
|
}
|
|
1001
|
-
/**
|
|
1002
|
-
* Leader-election primitive for indexer singletons.
|
|
1003
|
-
*
|
|
1004
|
-
* **Why this exists (audit finding H-04):** the `BurnIndexer` and
|
|
1005
|
-
* `PointIndexer` classes are stateful polling loops with a cursor
|
|
1006
|
-
* stored in an external store. Running them on multiple replicas
|
|
1007
|
-
* simultaneously causes:
|
|
1008
|
-
*
|
|
1009
|
-
* 1. Double-credit — both replicas see the same Transfer event
|
|
1010
|
-
* and call `ledger.resolveCreditByBurnTx` twice.
|
|
1011
|
-
* 2. Cursor rewind — last-writer-wins `save()` causes the newer
|
|
1012
|
-
* cursor to be overwritten by a lagging replica's older value,
|
|
1013
|
-
* causing the next poll to replay events.
|
|
1014
|
-
* 3. Skipped blocks — chunked range reads can leave gaps when two
|
|
1015
|
-
* replicas race-advance the cursor.
|
|
1016
|
-
*
|
|
1017
|
-
* **Adoption:** pass `singletonLock` into `IssuerServiceConfig.indexer`
|
|
1018
|
-
* (or wire it directly in your provider). The factory will only call
|
|
1019
|
-
* `indexer.start()` on the indexers it successfully acquires a lock
|
|
1020
|
-
* for; the rest stay idle and take over instantly on lock release.
|
|
1021
|
-
*
|
|
1022
|
-
* **Implementations:** `makePostgresSingletonLock(dataSource)` (recommended
|
|
1023
|
-
* — uses `pg_try_advisory_lock`, auto-releases on connection close).
|
|
1024
|
-
* You can also bring your own: Redis SETNX with TTL, etcd lease, etc.
|
|
1025
|
-
*/
|
|
1026
1021
|
interface ISingletonLock {
|
|
1027
1022
|
/**
|
|
1028
1023
|
* Attempt to acquire the lock for `key`. Returns a handle on success
|
|
@@ -1034,6 +1029,23 @@ interface ISingletonLock {
|
|
|
1034
1029
|
acquire(key: string): Promise<SingletonLockHandle | null>;
|
|
1035
1030
|
}
|
|
1036
1031
|
|
|
1032
|
+
declare class PointIndexerFinalizeError extends Error {
|
|
1033
|
+
readonly context: {
|
|
1034
|
+
pointToken: Address;
|
|
1035
|
+
to: Address;
|
|
1036
|
+
amount: bigint;
|
|
1037
|
+
txHash: `0x${string}`;
|
|
1038
|
+
blockNumber: bigint;
|
|
1039
|
+
};
|
|
1040
|
+
readonly cause: unknown;
|
|
1041
|
+
constructor(message: string, context: {
|
|
1042
|
+
pointToken: Address;
|
|
1043
|
+
to: Address;
|
|
1044
|
+
amount: bigint;
|
|
1045
|
+
txHash: `0x${string}`;
|
|
1046
|
+
blockNumber: bigint;
|
|
1047
|
+
}, cause: unknown);
|
|
1048
|
+
}
|
|
1037
1049
|
interface PointIndexerConfig {
|
|
1038
1050
|
provider: PublicClient;
|
|
1039
1051
|
pointTokenAddress: Address;
|
|
@@ -1184,6 +1196,33 @@ declare class PointIndexer {
|
|
|
1184
1196
|
private finalize;
|
|
1185
1197
|
}
|
|
1186
1198
|
|
|
1199
|
+
/**
|
|
1200
|
+
* Mirror of `PointIndexerFinalizeError` — raised when
|
|
1201
|
+
* `ledger.resolveCreditByBurnTx` rejects. See audit M-12: pre-fix this
|
|
1202
|
+
* was silently swallowed and the cursor advanced regardless,
|
|
1203
|
+
* permanently dropping confirmed on-chain burns from the off-chain
|
|
1204
|
+
* credit pipeline. Post-fix the error propagates, the chunk's cursor
|
|
1205
|
+
* save is skipped, and the next tick retries.
|
|
1206
|
+
*/
|
|
1207
|
+
declare class BurnIndexerFinalizeError extends Error {
|
|
1208
|
+
readonly context: {
|
|
1209
|
+
pointToken: Address;
|
|
1210
|
+
from: Address;
|
|
1211
|
+
amount: bigint;
|
|
1212
|
+
txHash: `0x${string}`;
|
|
1213
|
+
blockNumber: bigint;
|
|
1214
|
+
lockId: string;
|
|
1215
|
+
};
|
|
1216
|
+
readonly cause: unknown;
|
|
1217
|
+
constructor(message: string, context: {
|
|
1218
|
+
pointToken: Address;
|
|
1219
|
+
from: Address;
|
|
1220
|
+
amount: bigint;
|
|
1221
|
+
txHash: `0x${string}`;
|
|
1222
|
+
blockNumber: bigint;
|
|
1223
|
+
lockId: string;
|
|
1224
|
+
}, cause: unknown);
|
|
1225
|
+
}
|
|
1187
1226
|
interface BurnIndexerConfig {
|
|
1188
1227
|
provider: PublicClient;
|
|
1189
1228
|
pointTokenAddress: Address;
|
|
@@ -1242,7 +1281,7 @@ declare class BurnIndexer {
|
|
|
1242
1281
|
private readonly provider;
|
|
1243
1282
|
/**
|
|
1244
1283
|
* The PointToken this indexer watches. Exposed so callers can key
|
|
1245
|
-
* leader-election locks / cursor stores by token
|
|
1284
|
+
* leader-election locks / cursor stores by token
|
|
1246
1285
|
*/
|
|
1247
1286
|
readonly pointTokenAddress: Address;
|
|
1248
1287
|
private readonly ledger;
|
|
@@ -3651,34 +3690,48 @@ declare function relayUserOp(params: RelayUserOpParams): Promise<{
|
|
|
3651
3690
|
userOpHash: Hex;
|
|
3652
3691
|
}>;
|
|
3653
3692
|
|
|
3693
|
+
/**
|
|
3694
|
+
* Registry record returned by `IssuerRegistry.getIssuer()` in V2
|
|
3695
|
+
* dual-bucket. Schema reshape from V1:
|
|
3696
|
+
*
|
|
3697
|
+
* V1: { issuerAddress, signerAddress, name, symbol, active, pointToken, mintingOracle }
|
|
3698
|
+
* V2: { signerAddress, name, active, capitalBase, basisPoints }
|
|
3699
|
+
*
|
|
3700
|
+
* `issuerAddress` is the lookup key the caller passed; we don't
|
|
3701
|
+
* re-emit it here because the caller already has it. `capitalBase` +
|
|
3702
|
+
* `basisPoints` drive the EQUITY-bucket cap (`capitalBase *
|
|
3703
|
+
* basisPoints / 10000`).
|
|
3704
|
+
*/
|
|
3654
3705
|
interface IssuerRegistryRecord {
|
|
3655
|
-
issuerAddress: Address;
|
|
3656
3706
|
signerAddress: Address;
|
|
3657
3707
|
name: string;
|
|
3658
|
-
symbol: string;
|
|
3659
3708
|
active: boolean;
|
|
3660
|
-
|
|
3661
|
-
|
|
3709
|
+
capitalBase: bigint;
|
|
3710
|
+
basisPoints: number;
|
|
3662
3711
|
}
|
|
3663
3712
|
/**
|
|
3664
|
-
*
|
|
3665
|
-
*
|
|
3666
|
-
*
|
|
3713
|
+
* Equity-bucket cap snapshot computed from the `IssuerRegistryRecord`.
|
|
3714
|
+
*
|
|
3715
|
+
* V1 had a separate `TokenCapRecord` sourced from
|
|
3716
|
+
* `MintingOracle.tokenCaps`; in V2 the oracle is stateless and the
|
|
3717
|
+
* EQUITY cap derives from the registry's `capitalBase` + `basisPoints`.
|
|
3718
|
+
* Kept as a distinct shape (rather than inlining into
|
|
3719
|
+
* `PreValidateMintResult`) so admin tooling can read it without
|
|
3720
|
+
* re-deriving the multiplication.
|
|
3667
3721
|
*/
|
|
3668
|
-
interface
|
|
3669
|
-
|
|
3670
|
-
|
|
3722
|
+
interface EquityCapRecord {
|
|
3723
|
+
capitalBase: bigint;
|
|
3724
|
+
basisPoints: number;
|
|
3725
|
+
hardCap: bigint;
|
|
3671
3726
|
}
|
|
3672
3727
|
interface PreValidateMintResult {
|
|
3673
3728
|
/** Registry record read at pre-validation time. */
|
|
3674
3729
|
issuer: IssuerRegistryRecord;
|
|
3675
|
-
/**
|
|
3676
|
-
|
|
3677
|
-
/** Current on-chain PointToken.
|
|
3678
|
-
|
|
3679
|
-
/**
|
|
3680
|
-
hardCap: bigint;
|
|
3681
|
-
/** hardCap − totalSupply (clamped to 0). */
|
|
3730
|
+
/** Equity-bucket cap derived from issuer.capitalBase × basisPoints. */
|
|
3731
|
+
equityCap: EquityCapRecord;
|
|
3732
|
+
/** Current on-chain `PointToken.equitySupply()`. */
|
|
3733
|
+
equitySupply: bigint;
|
|
3734
|
+
/** equityCap.hardCap − equitySupply (clamped to 0). */
|
|
3682
3735
|
remaining: bigint;
|
|
3683
3736
|
}
|
|
3684
3737
|
/**
|
|
@@ -3832,4 +3885,4 @@ declare class MemoryRedemptionHistoryStore implements IRedemptionHistoryStore {
|
|
|
3832
3885
|
|
|
3833
3886
|
declare const PAFI_ISSUER_SDK_VERSION: string;
|
|
3834
3887
|
|
|
3835
|
-
export { AdapterMisconfiguredError, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedemptionEvaluateRequest, type ApiRedemptionEvaluateResponse, type ApiRedemptionPreviewRequest, type ApiRedemptionPreviewResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig, type BundlerEstimatorClient, BundlerNotConfiguredError, BundlerRejectedError, type BurnEvent, BurnIndexer, type BurnIndexerConfig, type BurnStatusParams, type BurnStatusResponse, type ClaimDto, type ConfigDto, ConfigurationError, DEFAULT_REDEMPTION_POLICY, type DecodedCallDto, DefaultPolicyEngine, type DefaultPolicyEngineOptions, type DelegatePrepareDto, type DelegateStatusDto, type EstimateGasFeeOptions, type EvaluateInput, FeeManager, type FeeManagerConfig, type FeeManagerMetrics, type FetchFailureReason, type FetchImpl, type FetchResult, type GasFeeDto, type GasFeeSource, type HandleDelegateSubmitParams, type HandleDelegateSubmitResult, type HandleMobilePrepareParams, type HandleMobilePrepareResult, type HandleMobileSubmitParams, type IIndexerCursorStore, type IPendingUserOpStore, type IPointLedger, type IPolicyEngine, type IRateLimiter, type IRedemptionHistoryStore, type ISessionStore, type ISingletonLock, InMemoryCursorStore, IssuerApiAdapter, type IssuerApiAdapterConfig, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerRegistryRecord, type IssuerService, type IssuerServiceConfig, IssuerStateError, IssuerStateValidator, LockNotFoundError, type LockedMintRequest, type LoginResult, MemoryPendingUserOpStore, MemoryRateLimiter, MemoryRedemptionHistoryStore, MemorySessionStore, type MemorySessionStoreOptions, type MintEvent, type MintStatusParams, type MintStatusResponse, type MintingStatus, type MobilePrepareDto, type MobileSubmitDto, type NativePtQuoterConfig, NonceManager, NoopRateLimiter, PAFI_ISSUER_SDK_VERSION, PTClaimError, PTClaimHandler, type PTClaimHandlerConfig, type PTClaimRequest, type PTClaimResponse, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, type PafiEstimatorClientConfig, PafiEstimatorHttpError, type PaymasterGasEstimates, type PendingCredit, type PendingUserOpEntry, PendingUserOpForbiddenError, PendingUserOpNotFoundError, type PerpDepositDto, PerpDepositError, PerpDepositHandler, type PerpDepositHandlerConfig, type PerpDepositRequest, type PerpDepositResponse, PointIndexer, type PointIndexerConfig, PointTokenDomainResolver, type PointTokenDomainResolverConfig, type PolicyDecision, type PolicyEvalRequest, PolicyProvider, type PolicyProviderConfig, type PoolsDto, type PoolsProvider, type PostgresQueryRunner, type PreValidateMintResult, type PrepareBurnParams, type PrepareMintParams, type PrepareMobileUserOpParams, type PrepareMobileUserOpResult, type PreparedUserOp, type PreviewBurnParams, type PreviewMintParams, REDEMPTION_HISTORY_WINDOW_SEC, type RateLimitAction, type RateLimiterConfig, type RedeemDto, type RedeemPrepareDto, RedemptionService, type RedemptionServiceConfig, RelayError, type RelayErrorCode, RelayService, type RelayUserOpParams, type RelayUserOpRequest, type RelayUserOpResponse, type RequestPaymasterParams, type ResolvedPolicy, type RetryConfig, type SdkErrorBody, type SdkErrorMapperFactories, type SdkErrorStatus, type SerializedUserOpTypedData, type Session, SettlementClient, type SettlementClientConfig, type SingletonLockHandle, type SponsorshipRequest, type SponsorshipResponse, type SponsorshipTarget, type SponsorshipUserOp, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, type UserDto, type UserHistory, applyPaymasterGasEstimates, authenticateRequest, buildSdkErrorBody, createIssuerService, createNativePtQuoter, createPafiEstimatorClient, createSdkErrorMapper, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, defaultPolicyFor, evaluateRedemption, handleClaimStatus, handleDelegateSubmit, handleMobilePrepare, handleMobileSubmit, handleRedeemStatus, makePostgresSingletonLock, mergePaymasterFields, prepareMobileUserOp, relayUserOp, requestPaymaster, serializeEntryToJsonRpc, serializeUserOpTypedData };
|
|
3888
|
+
export { AdapterMisconfiguredError, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedemptionEvaluateRequest, type ApiRedemptionEvaluateResponse, type ApiRedemptionPreviewRequest, type ApiRedemptionPreviewResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig, type BundlerEstimatorClient, BundlerNotConfiguredError, BundlerRejectedError, type BurnEvent, BurnIndexer, type BurnIndexerConfig, BurnIndexerFinalizeError, type BurnStatusParams, type BurnStatusResponse, type ClaimDto, type ConfigDto, ConfigurationError, DEFAULT_REDEMPTION_POLICY, type DecodedCallDto, DefaultPolicyEngine, type DefaultPolicyEngineOptions, type DelegatePrepareDto, type DelegateStatusDto, type EstimateGasFeeOptions, type EvaluateInput, FeeManager, type FeeManagerConfig, type FeeManagerMetrics, type FetchFailureReason, type FetchImpl, type FetchResult, type GasFeeDto, type GasFeeSource, type HandleDelegateSubmitParams, type HandleDelegateSubmitResult, type HandleMobilePrepareParams, type HandleMobilePrepareResult, type HandleMobileSubmitParams, type IIndexerCursorStore, type IPendingUserOpStore, type IPointLedger, type IPolicyEngine, type IRateLimiter, type IRedemptionHistoryStore, type ISessionStore, type ISingletonLock, InMemoryCursorStore, IssuerApiAdapter, type IssuerApiAdapterConfig, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerRegistryRecord, type IssuerService, type IssuerServiceConfig, IssuerStateError, IssuerStateValidator, LockNotFoundError, type LockedMintRequest, type LoginResult, MemoryPendingUserOpStore, MemoryRateLimiter, MemoryRedemptionHistoryStore, MemorySessionStore, type MemorySessionStoreOptions, type MintEvent, type MintStatusParams, type MintStatusResponse, type MintingStatus, type MobilePrepareDto, type MobileSubmitDto, type NativePtQuoterConfig, NonceManager, NoopRateLimiter, PAFI_ISSUER_SDK_VERSION, PTClaimError, PTClaimHandler, type PTClaimHandlerConfig, type PTClaimRequest, type PTClaimResponse, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, type PafiEstimatorClientConfig, PafiEstimatorHttpError, type PaymasterGasEstimates, type PendingCredit, type PendingUserOpEntry, PendingUserOpForbiddenError, PendingUserOpNotFoundError, type PerpDepositDto, PerpDepositError, PerpDepositHandler, type PerpDepositHandlerConfig, type PerpDepositRequest, type PerpDepositResponse, PointIndexer, type PointIndexerConfig, PointIndexerFinalizeError, PointTokenDomainResolver, type PointTokenDomainResolverConfig, type PolicyDecision, type PolicyEvalRequest, PolicyProvider, type PolicyProviderConfig, type PoolsDto, type PoolsProvider, type PostgresQueryRunner, type PreValidateMintResult, type PrepareBurnParams, type PrepareMintParams, type PrepareMobileUserOpParams, type PrepareMobileUserOpResult, type PreparedUserOp, type PreviewBurnParams, type PreviewMintParams, REDEMPTION_HISTORY_WINDOW_SEC, type RateLimitAction, type RateLimiterConfig, type RedeemDto, type RedeemPrepareDto, RedemptionService, type RedemptionServiceConfig, RelayError, type RelayErrorCode, RelayService, type RelayUserOpParams, type RelayUserOpRequest, type RelayUserOpResponse, type RequestPaymasterParams, type ResolvedPolicy, type RetryConfig, type SdkErrorBody, type SdkErrorMapperFactories, type SdkErrorStatus, type SerializedUserOpTypedData, type Session, SettlementClient, type SettlementClientConfig, type SingletonLockHandle, type SponsorshipRequest, type SponsorshipResponse, type SponsorshipTarget, type SponsorshipUserOp, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, type UserDto, type UserHistory, applyPaymasterGasEstimates, authenticateRequest, buildSdkErrorBody, createIssuerService, createNativePtQuoter, createPafiEstimatorClient, createSdkErrorMapper, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, defaultPolicyFor, evaluateRedemption, handleClaimStatus, handleDelegateSubmit, handleMobilePrepare, handleMobileSubmit, handleRedeemStatus, makePostgresSingletonLock, mergePaymasterFields, prepareMobileUserOp, relayUserOp, requestPaymaster, serializeEntryToJsonRpc, serializeUserOpTypedData };
|
package/dist/index.d.ts
CHANGED
|
@@ -967,12 +967,37 @@ interface BurnEvent {
|
|
|
967
967
|
* number it is about to process so the caller can write it to Redis /
|
|
968
968
|
* Postgres / a file. The SDK does not own persistence because every
|
|
969
969
|
* issuer has their own storage stack.
|
|
970
|
+
*
|
|
971
|
+
* **Per-token keying (audit finding H-05).** When multiple PointTokens
|
|
972
|
+
* are wired through a single `createIssuerService` call, each
|
|
973
|
+
* `PointIndexer` MUST get its own cursor — otherwise token A advances
|
|
974
|
+
* the shared cursor past token B's events and token B's mints are
|
|
975
|
+
* never finalized (off-chain balance never deducts → on-chain PT
|
|
976
|
+
* supply for token B exceeds off-chain backing). Combined with the
|
|
977
|
+
* H-04 monotonic-save fix this becomes a catastrophic-and-stable
|
|
978
|
+
* state where token B's cursor can never catch up. Implementations
|
|
979
|
+
* SHOULD expose `forKey(key)` returning a derived store keyed under
|
|
980
|
+
* a distinct namespace; the SDK factory calls it once per token.
|
|
981
|
+
*
|
|
982
|
+
* When `forKey` is absent, the SDK falls back to the bare store and
|
|
983
|
+
* emits a runtime warning if more than one token is configured. New
|
|
984
|
+
* implementations are strongly encouraged to add `forKey`.
|
|
970
985
|
*/
|
|
971
986
|
interface IIndexerCursorStore {
|
|
972
987
|
/** Return the last persisted cursor (`undefined` on first run). */
|
|
973
988
|
load(): Promise<bigint | undefined>;
|
|
974
989
|
/** Persist a new cursor value. Called after each successful batch. */
|
|
975
990
|
save(blockNumber: bigint): Promise<void>;
|
|
991
|
+
/**
|
|
992
|
+
* Return a derived store keyed under `key`. The returned store is
|
|
993
|
+
* an independent `IIndexerCursorStore` so the same persistence
|
|
994
|
+
* backend can serve N indexers with N distinct cursors.
|
|
995
|
+
*
|
|
996
|
+
* Optional for backwards compatibility, but REQUIRED in practice
|
|
997
|
+
* whenever more than one PointToken is wired through the SDK
|
|
998
|
+
* factory (see H-05).
|
|
999
|
+
*/
|
|
1000
|
+
forKey?(key: string): IIndexerCursorStore;
|
|
976
1001
|
}
|
|
977
1002
|
/**
|
|
978
1003
|
* No-op cursor store. Useful when the caller wants to drive the cursor
|
|
@@ -980,49 +1005,19 @@ interface IIndexerCursorStore {
|
|
|
980
1005
|
*/
|
|
981
1006
|
declare class InMemoryCursorStore implements IIndexerCursorStore {
|
|
982
1007
|
private cursor;
|
|
1008
|
+
/**
|
|
1009
|
+
* Child stores keyed by `forKey()`. Each child has its own cursor
|
|
1010
|
+
* (the H-05 fix), so a single InMemoryCursorStore can back N
|
|
1011
|
+
* PointIndexers in tests / single-process callers.
|
|
1012
|
+
*/
|
|
1013
|
+
private readonly children;
|
|
983
1014
|
load(): Promise<bigint | undefined>;
|
|
984
1015
|
save(blockNumber: bigint): Promise<void>;
|
|
1016
|
+
forKey(key: string): IIndexerCursorStore;
|
|
985
1017
|
}
|
|
986
|
-
/**
|
|
987
|
-
* Lock handle returned by a successful `ISingletonLock.acquire()`.
|
|
988
|
-
*
|
|
989
|
-
* The holder is the leader for the keyed indexer; non-holders MUST NOT
|
|
990
|
-
* call `indexer.start()` (else they race against the leader's polling
|
|
991
|
-
* loop and last-writer-wins cursor save corrupts replay state).
|
|
992
|
-
*
|
|
993
|
-
* `release()` is called by the leader on graceful shutdown. If the
|
|
994
|
-
* leader crashes without calling release, the lock implementation
|
|
995
|
-
* MUST drop the lock automatically (e.g. Postgres advisory locks
|
|
996
|
-
* auto-release on connection close).
|
|
997
|
-
*/
|
|
998
1018
|
interface SingletonLockHandle {
|
|
999
1019
|
release(): Promise<void>;
|
|
1000
1020
|
}
|
|
1001
|
-
/**
|
|
1002
|
-
* Leader-election primitive for indexer singletons.
|
|
1003
|
-
*
|
|
1004
|
-
* **Why this exists (audit finding H-04):** the `BurnIndexer` and
|
|
1005
|
-
* `PointIndexer` classes are stateful polling loops with a cursor
|
|
1006
|
-
* stored in an external store. Running them on multiple replicas
|
|
1007
|
-
* simultaneously causes:
|
|
1008
|
-
*
|
|
1009
|
-
* 1. Double-credit — both replicas see the same Transfer event
|
|
1010
|
-
* and call `ledger.resolveCreditByBurnTx` twice.
|
|
1011
|
-
* 2. Cursor rewind — last-writer-wins `save()` causes the newer
|
|
1012
|
-
* cursor to be overwritten by a lagging replica's older value,
|
|
1013
|
-
* causing the next poll to replay events.
|
|
1014
|
-
* 3. Skipped blocks — chunked range reads can leave gaps when two
|
|
1015
|
-
* replicas race-advance the cursor.
|
|
1016
|
-
*
|
|
1017
|
-
* **Adoption:** pass `singletonLock` into `IssuerServiceConfig.indexer`
|
|
1018
|
-
* (or wire it directly in your provider). The factory will only call
|
|
1019
|
-
* `indexer.start()` on the indexers it successfully acquires a lock
|
|
1020
|
-
* for; the rest stay idle and take over instantly on lock release.
|
|
1021
|
-
*
|
|
1022
|
-
* **Implementations:** `makePostgresSingletonLock(dataSource)` (recommended
|
|
1023
|
-
* — uses `pg_try_advisory_lock`, auto-releases on connection close).
|
|
1024
|
-
* You can also bring your own: Redis SETNX with TTL, etcd lease, etc.
|
|
1025
|
-
*/
|
|
1026
1021
|
interface ISingletonLock {
|
|
1027
1022
|
/**
|
|
1028
1023
|
* Attempt to acquire the lock for `key`. Returns a handle on success
|
|
@@ -1034,6 +1029,23 @@ interface ISingletonLock {
|
|
|
1034
1029
|
acquire(key: string): Promise<SingletonLockHandle | null>;
|
|
1035
1030
|
}
|
|
1036
1031
|
|
|
1032
|
+
declare class PointIndexerFinalizeError extends Error {
|
|
1033
|
+
readonly context: {
|
|
1034
|
+
pointToken: Address;
|
|
1035
|
+
to: Address;
|
|
1036
|
+
amount: bigint;
|
|
1037
|
+
txHash: `0x${string}`;
|
|
1038
|
+
blockNumber: bigint;
|
|
1039
|
+
};
|
|
1040
|
+
readonly cause: unknown;
|
|
1041
|
+
constructor(message: string, context: {
|
|
1042
|
+
pointToken: Address;
|
|
1043
|
+
to: Address;
|
|
1044
|
+
amount: bigint;
|
|
1045
|
+
txHash: `0x${string}`;
|
|
1046
|
+
blockNumber: bigint;
|
|
1047
|
+
}, cause: unknown);
|
|
1048
|
+
}
|
|
1037
1049
|
interface PointIndexerConfig {
|
|
1038
1050
|
provider: PublicClient;
|
|
1039
1051
|
pointTokenAddress: Address;
|
|
@@ -1184,6 +1196,33 @@ declare class PointIndexer {
|
|
|
1184
1196
|
private finalize;
|
|
1185
1197
|
}
|
|
1186
1198
|
|
|
1199
|
+
/**
|
|
1200
|
+
* Mirror of `PointIndexerFinalizeError` — raised when
|
|
1201
|
+
* `ledger.resolveCreditByBurnTx` rejects. See audit M-12: pre-fix this
|
|
1202
|
+
* was silently swallowed and the cursor advanced regardless,
|
|
1203
|
+
* permanently dropping confirmed on-chain burns from the off-chain
|
|
1204
|
+
* credit pipeline. Post-fix the error propagates, the chunk's cursor
|
|
1205
|
+
* save is skipped, and the next tick retries.
|
|
1206
|
+
*/
|
|
1207
|
+
declare class BurnIndexerFinalizeError extends Error {
|
|
1208
|
+
readonly context: {
|
|
1209
|
+
pointToken: Address;
|
|
1210
|
+
from: Address;
|
|
1211
|
+
amount: bigint;
|
|
1212
|
+
txHash: `0x${string}`;
|
|
1213
|
+
blockNumber: bigint;
|
|
1214
|
+
lockId: string;
|
|
1215
|
+
};
|
|
1216
|
+
readonly cause: unknown;
|
|
1217
|
+
constructor(message: string, context: {
|
|
1218
|
+
pointToken: Address;
|
|
1219
|
+
from: Address;
|
|
1220
|
+
amount: bigint;
|
|
1221
|
+
txHash: `0x${string}`;
|
|
1222
|
+
blockNumber: bigint;
|
|
1223
|
+
lockId: string;
|
|
1224
|
+
}, cause: unknown);
|
|
1225
|
+
}
|
|
1187
1226
|
interface BurnIndexerConfig {
|
|
1188
1227
|
provider: PublicClient;
|
|
1189
1228
|
pointTokenAddress: Address;
|
|
@@ -1242,7 +1281,7 @@ declare class BurnIndexer {
|
|
|
1242
1281
|
private readonly provider;
|
|
1243
1282
|
/**
|
|
1244
1283
|
* The PointToken this indexer watches. Exposed so callers can key
|
|
1245
|
-
* leader-election locks / cursor stores by token
|
|
1284
|
+
* leader-election locks / cursor stores by token
|
|
1246
1285
|
*/
|
|
1247
1286
|
readonly pointTokenAddress: Address;
|
|
1248
1287
|
private readonly ledger;
|
|
@@ -3651,34 +3690,48 @@ declare function relayUserOp(params: RelayUserOpParams): Promise<{
|
|
|
3651
3690
|
userOpHash: Hex;
|
|
3652
3691
|
}>;
|
|
3653
3692
|
|
|
3693
|
+
/**
|
|
3694
|
+
* Registry record returned by `IssuerRegistry.getIssuer()` in V2
|
|
3695
|
+
* dual-bucket. Schema reshape from V1:
|
|
3696
|
+
*
|
|
3697
|
+
* V1: { issuerAddress, signerAddress, name, symbol, active, pointToken, mintingOracle }
|
|
3698
|
+
* V2: { signerAddress, name, active, capitalBase, basisPoints }
|
|
3699
|
+
*
|
|
3700
|
+
* `issuerAddress` is the lookup key the caller passed; we don't
|
|
3701
|
+
* re-emit it here because the caller already has it. `capitalBase` +
|
|
3702
|
+
* `basisPoints` drive the EQUITY-bucket cap (`capitalBase *
|
|
3703
|
+
* basisPoints / 10000`).
|
|
3704
|
+
*/
|
|
3654
3705
|
interface IssuerRegistryRecord {
|
|
3655
|
-
issuerAddress: Address;
|
|
3656
3706
|
signerAddress: Address;
|
|
3657
3707
|
name: string;
|
|
3658
|
-
symbol: string;
|
|
3659
3708
|
active: boolean;
|
|
3660
|
-
|
|
3661
|
-
|
|
3709
|
+
capitalBase: bigint;
|
|
3710
|
+
basisPoints: number;
|
|
3662
3711
|
}
|
|
3663
3712
|
/**
|
|
3664
|
-
*
|
|
3665
|
-
*
|
|
3666
|
-
*
|
|
3713
|
+
* Equity-bucket cap snapshot computed from the `IssuerRegistryRecord`.
|
|
3714
|
+
*
|
|
3715
|
+
* V1 had a separate `TokenCapRecord` sourced from
|
|
3716
|
+
* `MintingOracle.tokenCaps`; in V2 the oracle is stateless and the
|
|
3717
|
+
* EQUITY cap derives from the registry's `capitalBase` + `basisPoints`.
|
|
3718
|
+
* Kept as a distinct shape (rather than inlining into
|
|
3719
|
+
* `PreValidateMintResult`) so admin tooling can read it without
|
|
3720
|
+
* re-deriving the multiplication.
|
|
3667
3721
|
*/
|
|
3668
|
-
interface
|
|
3669
|
-
|
|
3670
|
-
|
|
3722
|
+
interface EquityCapRecord {
|
|
3723
|
+
capitalBase: bigint;
|
|
3724
|
+
basisPoints: number;
|
|
3725
|
+
hardCap: bigint;
|
|
3671
3726
|
}
|
|
3672
3727
|
interface PreValidateMintResult {
|
|
3673
3728
|
/** Registry record read at pre-validation time. */
|
|
3674
3729
|
issuer: IssuerRegistryRecord;
|
|
3675
|
-
/**
|
|
3676
|
-
|
|
3677
|
-
/** Current on-chain PointToken.
|
|
3678
|
-
|
|
3679
|
-
/**
|
|
3680
|
-
hardCap: bigint;
|
|
3681
|
-
/** hardCap − totalSupply (clamped to 0). */
|
|
3730
|
+
/** Equity-bucket cap derived from issuer.capitalBase × basisPoints. */
|
|
3731
|
+
equityCap: EquityCapRecord;
|
|
3732
|
+
/** Current on-chain `PointToken.equitySupply()`. */
|
|
3733
|
+
equitySupply: bigint;
|
|
3734
|
+
/** equityCap.hardCap − equitySupply (clamped to 0). */
|
|
3682
3735
|
remaining: bigint;
|
|
3683
3736
|
}
|
|
3684
3737
|
/**
|
|
@@ -3832,4 +3885,4 @@ declare class MemoryRedemptionHistoryStore implements IRedemptionHistoryStore {
|
|
|
3832
3885
|
|
|
3833
3886
|
declare const PAFI_ISSUER_SDK_VERSION: string;
|
|
3834
3887
|
|
|
3835
|
-
export { AdapterMisconfiguredError, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedemptionEvaluateRequest, type ApiRedemptionEvaluateResponse, type ApiRedemptionPreviewRequest, type ApiRedemptionPreviewResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig, type BundlerEstimatorClient, BundlerNotConfiguredError, BundlerRejectedError, type BurnEvent, BurnIndexer, type BurnIndexerConfig, type BurnStatusParams, type BurnStatusResponse, type ClaimDto, type ConfigDto, ConfigurationError, DEFAULT_REDEMPTION_POLICY, type DecodedCallDto, DefaultPolicyEngine, type DefaultPolicyEngineOptions, type DelegatePrepareDto, type DelegateStatusDto, type EstimateGasFeeOptions, type EvaluateInput, FeeManager, type FeeManagerConfig, type FeeManagerMetrics, type FetchFailureReason, type FetchImpl, type FetchResult, type GasFeeDto, type GasFeeSource, type HandleDelegateSubmitParams, type HandleDelegateSubmitResult, type HandleMobilePrepareParams, type HandleMobilePrepareResult, type HandleMobileSubmitParams, type IIndexerCursorStore, type IPendingUserOpStore, type IPointLedger, type IPolicyEngine, type IRateLimiter, type IRedemptionHistoryStore, type ISessionStore, type ISingletonLock, InMemoryCursorStore, IssuerApiAdapter, type IssuerApiAdapterConfig, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerRegistryRecord, type IssuerService, type IssuerServiceConfig, IssuerStateError, IssuerStateValidator, LockNotFoundError, type LockedMintRequest, type LoginResult, MemoryPendingUserOpStore, MemoryRateLimiter, MemoryRedemptionHistoryStore, MemorySessionStore, type MemorySessionStoreOptions, type MintEvent, type MintStatusParams, type MintStatusResponse, type MintingStatus, type MobilePrepareDto, type MobileSubmitDto, type NativePtQuoterConfig, NonceManager, NoopRateLimiter, PAFI_ISSUER_SDK_VERSION, PTClaimError, PTClaimHandler, type PTClaimHandlerConfig, type PTClaimRequest, type PTClaimResponse, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, type PafiEstimatorClientConfig, PafiEstimatorHttpError, type PaymasterGasEstimates, type PendingCredit, type PendingUserOpEntry, PendingUserOpForbiddenError, PendingUserOpNotFoundError, type PerpDepositDto, PerpDepositError, PerpDepositHandler, type PerpDepositHandlerConfig, type PerpDepositRequest, type PerpDepositResponse, PointIndexer, type PointIndexerConfig, PointTokenDomainResolver, type PointTokenDomainResolverConfig, type PolicyDecision, type PolicyEvalRequest, PolicyProvider, type PolicyProviderConfig, type PoolsDto, type PoolsProvider, type PostgresQueryRunner, type PreValidateMintResult, type PrepareBurnParams, type PrepareMintParams, type PrepareMobileUserOpParams, type PrepareMobileUserOpResult, type PreparedUserOp, type PreviewBurnParams, type PreviewMintParams, REDEMPTION_HISTORY_WINDOW_SEC, type RateLimitAction, type RateLimiterConfig, type RedeemDto, type RedeemPrepareDto, RedemptionService, type RedemptionServiceConfig, RelayError, type RelayErrorCode, RelayService, type RelayUserOpParams, type RelayUserOpRequest, type RelayUserOpResponse, type RequestPaymasterParams, type ResolvedPolicy, type RetryConfig, type SdkErrorBody, type SdkErrorMapperFactories, type SdkErrorStatus, type SerializedUserOpTypedData, type Session, SettlementClient, type SettlementClientConfig, type SingletonLockHandle, type SponsorshipRequest, type SponsorshipResponse, type SponsorshipTarget, type SponsorshipUserOp, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, type UserDto, type UserHistory, applyPaymasterGasEstimates, authenticateRequest, buildSdkErrorBody, createIssuerService, createNativePtQuoter, createPafiEstimatorClient, createSdkErrorMapper, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, defaultPolicyFor, evaluateRedemption, handleClaimStatus, handleDelegateSubmit, handleMobilePrepare, handleMobileSubmit, handleRedeemStatus, makePostgresSingletonLock, mergePaymasterFields, prepareMobileUserOp, relayUserOp, requestPaymaster, serializeEntryToJsonRpc, serializeUserOpTypedData };
|
|
3888
|
+
export { AdapterMisconfiguredError, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, type ApiRedemptionEvaluateRequest, type ApiRedemptionEvaluateResponse, type ApiRedemptionPreviewRequest, type ApiRedemptionPreviewResponse, type ApiUserRequest, type ApiUserResponse, type AuthContext, AuthError, type AuthErrorCode, AuthService, type AuthServiceConfig, type BundlerEstimatorClient, BundlerNotConfiguredError, BundlerRejectedError, type BurnEvent, BurnIndexer, type BurnIndexerConfig, BurnIndexerFinalizeError, type BurnStatusParams, type BurnStatusResponse, type ClaimDto, type ConfigDto, ConfigurationError, DEFAULT_REDEMPTION_POLICY, type DecodedCallDto, DefaultPolicyEngine, type DefaultPolicyEngineOptions, type DelegatePrepareDto, type DelegateStatusDto, type EstimateGasFeeOptions, type EvaluateInput, FeeManager, type FeeManagerConfig, type FeeManagerMetrics, type FetchFailureReason, type FetchImpl, type FetchResult, type GasFeeDto, type GasFeeSource, type HandleDelegateSubmitParams, type HandleDelegateSubmitResult, type HandleMobilePrepareParams, type HandleMobilePrepareResult, type HandleMobileSubmitParams, type IIndexerCursorStore, type IPendingUserOpStore, type IPointLedger, type IPolicyEngine, type IRateLimiter, type IRedemptionHistoryStore, type ISessionStore, type ISingletonLock, InMemoryCursorStore, IssuerApiAdapter, type IssuerApiAdapterConfig, IssuerApiHandlers, type IssuerApiHandlersConfig, type IssuerRegistryRecord, type IssuerService, type IssuerServiceConfig, IssuerStateError, IssuerStateValidator, LockNotFoundError, type LockedMintRequest, type LoginResult, MemoryPendingUserOpStore, MemoryRateLimiter, MemoryRedemptionHistoryStore, MemorySessionStore, type MemorySessionStoreOptions, type MintEvent, type MintStatusParams, type MintStatusResponse, type MintingStatus, type MobilePrepareDto, type MobileSubmitDto, type NativePtQuoterConfig, NonceManager, NoopRateLimiter, PAFI_ISSUER_SDK_VERSION, PTClaimError, PTClaimHandler, type PTClaimHandlerConfig, type PTClaimRequest, type PTClaimResponse, PTRedeemError, PTRedeemHandler, type PTRedeemHandlerConfig, type PTRedeemRequest, type PTRedeemResponse, PafiBackendClient, type PafiBackendConfig, PafiBackendError, type PafiBackendErrorCode, type PafiEstimatorClientConfig, PafiEstimatorHttpError, type PaymasterGasEstimates, type PendingCredit, type PendingUserOpEntry, PendingUserOpForbiddenError, PendingUserOpNotFoundError, type PerpDepositDto, PerpDepositError, PerpDepositHandler, type PerpDepositHandlerConfig, type PerpDepositRequest, type PerpDepositResponse, PointIndexer, type PointIndexerConfig, PointIndexerFinalizeError, PointTokenDomainResolver, type PointTokenDomainResolverConfig, type PolicyDecision, type PolicyEvalRequest, PolicyProvider, type PolicyProviderConfig, type PoolsDto, type PoolsProvider, type PostgresQueryRunner, type PreValidateMintResult, type PrepareBurnParams, type PrepareMintParams, type PrepareMobileUserOpParams, type PrepareMobileUserOpResult, type PreparedUserOp, type PreviewBurnParams, type PreviewMintParams, REDEMPTION_HISTORY_WINDOW_SEC, type RateLimitAction, type RateLimiterConfig, type RedeemDto, type RedeemPrepareDto, RedemptionService, type RedemptionServiceConfig, RelayError, type RelayErrorCode, RelayService, type RelayUserOpParams, type RelayUserOpRequest, type RelayUserOpResponse, type RequestPaymasterParams, type ResolvedPolicy, type RetryConfig, type SdkErrorBody, type SdkErrorMapperFactories, type SdkErrorStatus, type SerializedUserOpTypedData, type Session, SettlementClient, type SettlementClientConfig, type SingletonLockHandle, type SponsorshipRequest, type SponsorshipResponse, type SponsorshipTarget, type SponsorshipUserOp, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, type UserDto, type UserHistory, applyPaymasterGasEstimates, authenticateRequest, buildSdkErrorBody, createIssuerService, createNativePtQuoter, createPafiEstimatorClient, createSdkErrorMapper, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider, defaultPolicyFor, evaluateRedemption, handleClaimStatus, handleDelegateSubmit, handleMobilePrepare, handleMobileSubmit, handleRedeemStatus, makePostgresSingletonLock, mergePaymasterFields, prepareMobileUserOp, relayUserOp, requestPaymaster, serializeEntryToJsonRpc, serializeUserOpTypedData };
|