@pafi-dev/issuer 0.3.0-beta.1 → 0.3.0-beta.11
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/README.md +164 -292
- package/dist/index.cjs +437 -1029
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +234 -616
- package/dist/index.d.ts +234 -616
- package/dist/index.js +421 -1013
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import { Address, Hex, PublicClient,
|
|
2
|
-
import { PointTokenDomainConfig,
|
|
3
|
-
export { encodeExtData } from '@pafi-dev/core';
|
|
1
|
+
import { Address, Hex, PublicClient, WalletClient } from 'viem';
|
|
2
|
+
import { PointTokenDomainConfig, PartialUserOperation, BurnRequest, ReceiverConsent, PathKey, PoolKey } from '@pafi-dev/core';
|
|
4
3
|
|
|
5
4
|
/**
|
|
6
5
|
* Lifecycle of a minting request as tracked by the issuer's point ledger.
|
|
@@ -63,11 +62,7 @@ interface IPointLedger {
|
|
|
63
62
|
lockForMinting(userAddress: Address, amount: bigint, lockDurationMs: number, tokenAddress?: Address): Promise<string>;
|
|
64
63
|
/** Release a previously created lock (e.g. on tx failure / cancel). */
|
|
65
64
|
releaseLock(lockId: string): Promise<void>;
|
|
66
|
-
/**
|
|
67
|
-
* Permanently deduct an amount from a user's balance after the on-chain
|
|
68
|
-
* mint has been observed by the indexer. Should also resolve any matching
|
|
69
|
-
* lock so the funds aren't double-counted.
|
|
70
|
-
*/
|
|
65
|
+
/** Deduct balance after a confirmed on-chain mint. Idempotent on `txHash`. */
|
|
71
66
|
deductBalance(userAddress: Address, amount: bigint, txHash: Hex, tokenAddress?: Address): Promise<void>;
|
|
72
67
|
/** Credit points to a user's balance (e.g. from merchant activity). */
|
|
73
68
|
creditBalance(userAddress: Address, amount: bigint, reason: string, tokenAddress?: Address): Promise<void>;
|
|
@@ -98,47 +93,6 @@ interface IPointLedger {
|
|
|
98
93
|
resolveCreditByBurnTx?(lockId: string, txHash: Hex): Promise<void>;
|
|
99
94
|
}
|
|
100
95
|
|
|
101
|
-
/**
|
|
102
|
-
* In-memory IPointLedger implementation for development and tests.
|
|
103
|
-
*
|
|
104
|
-
* NOT for production — state is lost on restart. Issuers should ship their
|
|
105
|
-
* own database-backed implementation.
|
|
106
|
-
*
|
|
107
|
-
* Concurrency model: single-process, single-threaded (Node.js event loop).
|
|
108
|
-
* The lock check + insert is atomic within a tick because no awaits sit
|
|
109
|
-
* between balance read and lock write.
|
|
110
|
-
*
|
|
111
|
-
* **Multi-token (0.2.0):** Balances are keyed by `(user, token)`. If callers
|
|
112
|
-
* omit `tokenAddress`, the literal string "default" is used — that keeps
|
|
113
|
-
* single-token usage working exactly like 0.1.x.
|
|
114
|
-
*/
|
|
115
|
-
declare class MemoryPointLedger implements IPointLedger {
|
|
116
|
-
private balances;
|
|
117
|
-
private locks;
|
|
118
|
-
private nextLockId;
|
|
119
|
-
private now;
|
|
120
|
-
constructor(opts?: {
|
|
121
|
-
now?: () => number;
|
|
122
|
-
});
|
|
123
|
-
getBalance(userAddress: Address, tokenAddress?: Address): Promise<bigint>;
|
|
124
|
-
getLockedRequests(userAddress: Address, tokenAddress?: Address): Promise<LockedMintRequest[]>;
|
|
125
|
-
creditBalance(userAddress: Address, amount: bigint, _reason: string, tokenAddress?: Address): Promise<void>;
|
|
126
|
-
lockForMinting(userAddress: Address, amount: bigint, lockDurationMs: number, tokenAddress?: Address): Promise<string>;
|
|
127
|
-
releaseLock(lockId: string): Promise<void>;
|
|
128
|
-
deductBalance(userAddress: Address, amount: bigint, txHash: Hex, tokenAddress?: Address): Promise<void>;
|
|
129
|
-
updateMintStatus(lockId: string, status: MintingStatus, txHash?: Hex): Promise<void>;
|
|
130
|
-
private pendingCredits;
|
|
131
|
-
private nextCreditId;
|
|
132
|
-
reservePendingCredit(userAddress: Address, amount: bigint, durationMs: number, tokenAddress?: Address): Promise<string>;
|
|
133
|
-
resolveCreditByBurnTx(lockId: string, txHash: Hex): Promise<void>;
|
|
134
|
-
/**
|
|
135
|
-
* Auto-expire any PENDING lock past its expiry. Called lazily on every
|
|
136
|
-
* read/write so the in-memory state stays self-cleaning without a timer.
|
|
137
|
-
*/
|
|
138
|
-
private purgeExpired;
|
|
139
|
-
private lockedTotalFor;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
96
|
/**
|
|
143
97
|
* Input to a policy evaluation. Policy engines use this to decide whether
|
|
144
98
|
* a user's mint request should be approved.
|
|
@@ -214,56 +168,6 @@ declare class DefaultPolicyEngine implements IPolicyEngine {
|
|
|
214
168
|
evaluate(request: PolicyEvalRequest): Promise<PolicyDecision>;
|
|
215
169
|
}
|
|
216
170
|
|
|
217
|
-
/**
|
|
218
|
-
* Issuer signer — produces the MintRequest EIP-712 signature that the Relay
|
|
219
|
-
* contract verifies against the issuer's on-chain authorized minter.
|
|
220
|
-
*
|
|
221
|
-
* This is a trust boundary: the default `PrivateKeySigner` holds the key in
|
|
222
|
-
* process memory and is intended for local development only. Production
|
|
223
|
-
* issuers replace this with an HSM/KMS/MPC integration.
|
|
224
|
-
*/
|
|
225
|
-
interface IIssuerSigner {
|
|
226
|
-
/**
|
|
227
|
-
* Sign a `MintRequest` message against the point token's EIP-712 domain.
|
|
228
|
-
* The returned signature is what the Relay contract passes to
|
|
229
|
-
* `PointToken.verify` during `mintAndSwap`.
|
|
230
|
-
*/
|
|
231
|
-
signMintRequest(domain: PointTokenDomainConfig, message: MintRequest): Promise<EIP712Signature>;
|
|
232
|
-
/** Get the signer's on-chain address (used for verification / logging). */
|
|
233
|
-
getAddress(): Promise<Address>;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
interface PrivateKeySignerOptions {
|
|
237
|
-
/** 0x-prefixed 32-byte hex private key */
|
|
238
|
-
privateKey: Hex;
|
|
239
|
-
/**
|
|
240
|
-
* Chain metadata for the viem WalletClient. Only the chain id is actually
|
|
241
|
-
* used for signing; a minimal stub is acceptable (it does not need to
|
|
242
|
-
* match the deployed chain config beyond id).
|
|
243
|
-
*/
|
|
244
|
-
chain: Chain;
|
|
245
|
-
/**
|
|
246
|
-
* Optional RPC URL. `signTypedData` is offline, so this can usually be
|
|
247
|
-
* left unset — viem only requires a transport to construct the client.
|
|
248
|
-
*/
|
|
249
|
-
rpcUrl?: string;
|
|
250
|
-
}
|
|
251
|
-
/**
|
|
252
|
-
* Local-key implementation of `IIssuerSigner`. Wraps viem's `signTypedData`
|
|
253
|
-
* via the shared `@pafi/core` `signMintRequest` helper.
|
|
254
|
-
*
|
|
255
|
-
* ⚠️ **NOT for production use.** The private key lives in process memory
|
|
256
|
-
* and is trivially extractable from a compromised host. Replace with an
|
|
257
|
-
* HSM/KMS/MPC-backed `IIssuerSigner` before deployment.
|
|
258
|
-
*/
|
|
259
|
-
declare class PrivateKeySigner implements IIssuerSigner {
|
|
260
|
-
private readonly account;
|
|
261
|
-
private readonly walletClient;
|
|
262
|
-
constructor(opts: PrivateKeySignerOptions);
|
|
263
|
-
signMintRequest(domain: PointTokenDomainConfig, message: MintRequest): Promise<EIP712Signature>;
|
|
264
|
-
getAddress(): Promise<Address>;
|
|
265
|
-
}
|
|
266
|
-
|
|
267
171
|
/**
|
|
268
172
|
* A server-issued session created after a successful wallet login. The
|
|
269
173
|
* token id is embedded in the JWT so sessions can be revoked without
|
|
@@ -449,168 +353,93 @@ declare class AuthError extends Error {
|
|
|
449
353
|
}
|
|
450
354
|
|
|
451
355
|
/**
|
|
452
|
-
*
|
|
453
|
-
*
|
|
454
|
-
*
|
|
455
|
-
*
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
swap: SwapParams;
|
|
460
|
-
}
|
|
461
|
-
/**
|
|
462
|
-
* Result of a relay submission. `txHash` is returned immediately after
|
|
463
|
-
* the tx is broadcast; `receipt` is present only when the caller opted to
|
|
464
|
-
* wait for confirmation.
|
|
465
|
-
*/
|
|
466
|
-
interface RelayResult {
|
|
467
|
-
txHash: Hex;
|
|
468
|
-
blockNumber?: bigint;
|
|
469
|
-
gasUsed?: bigint;
|
|
470
|
-
status?: "success" | "reverted";
|
|
471
|
-
}
|
|
472
|
-
/**
|
|
473
|
-
* Errors raised by RelayService carry a `code` so the MintingGateway (or
|
|
474
|
-
* any caller) can decide whether to release the ledger lock.
|
|
356
|
+
* Errors raised by RelayService carry a `code` so callers (handlers /
|
|
357
|
+
* gateway-less HTTP wrappers) can decide how to map them to HTTP status.
|
|
358
|
+
*
|
|
359
|
+
* v1.4 trimmed the error space to just encoding failures — the service
|
|
360
|
+
* no longer broadcasts transactions, so `SUBMIT_FAILED`, `TX_REVERTED`,
|
|
361
|
+
* `SIMULATION_FAILED`, and `TIMEOUT` all went away with the operator
|
|
362
|
+
* wallet. Paymaster/Bundler errors surface out-of-band on the FE.
|
|
475
363
|
*/
|
|
476
|
-
type RelayErrorCode = "NOT_CONFIGURED" | "ENCODE_FAILED"
|
|
364
|
+
type RelayErrorCode = "NOT_CONFIGURED" | "ENCODE_FAILED";
|
|
477
365
|
declare class RelayError extends Error {
|
|
478
366
|
readonly code: RelayErrorCode;
|
|
479
367
|
readonly cause?: unknown;
|
|
480
368
|
constructor(code: RelayErrorCode, message: string, cause?: unknown);
|
|
481
369
|
}
|
|
482
|
-
/**
|
|
483
|
-
* Interface an operator wallet must satisfy for the RelayService. Matches
|
|
484
|
-
* the subset of viem's `WalletClient` we actually call, so tests can pass
|
|
485
|
-
* a minimal mock instead of a full client.
|
|
486
|
-
*/
|
|
487
|
-
interface OperatorWalletLike {
|
|
488
|
-
writeContract: (args: {
|
|
489
|
-
address: Address;
|
|
490
|
-
abi: readonly unknown[];
|
|
491
|
-
functionName: string;
|
|
492
|
-
args: readonly unknown[];
|
|
493
|
-
account?: {
|
|
494
|
-
address: Address;
|
|
495
|
-
};
|
|
496
|
-
}) => Promise<Hex>;
|
|
497
|
-
account?: {
|
|
498
|
-
address: Address;
|
|
499
|
-
} | undefined;
|
|
500
|
-
}
|
|
501
370
|
|
|
502
|
-
interface RelayServiceConfig {
|
|
503
|
-
/** Address of the deployed Relay contract (chain-specific). */
|
|
504
|
-
relayAddress: Address;
|
|
505
|
-
/** Operator wallet that pays gas and receives the operator fee. */
|
|
506
|
-
operatorWallet: OperatorWalletLike;
|
|
507
|
-
/**
|
|
508
|
-
* Provider used for pre-flight simulation and receipt waiting. Optional —
|
|
509
|
-
* if omitted, the service still broadcasts but returns only `txHash`
|
|
510
|
-
* (caller is responsible for confirmation tracking).
|
|
511
|
-
*/
|
|
512
|
-
provider?: PublicClient;
|
|
513
|
-
/**
|
|
514
|
-
* If a provider is supplied, wait up to this many milliseconds for a
|
|
515
|
-
* receipt before timing out. Default: 60_000 (one minute).
|
|
516
|
-
*/
|
|
517
|
-
confirmationTimeoutMs?: number;
|
|
518
|
-
/**
|
|
519
|
-
* Whether to run `simulateContract` before submitting. Catches most
|
|
520
|
-
* reverts locally without wasting gas. Default: true (when provider is
|
|
521
|
-
* supplied).
|
|
522
|
-
*/
|
|
523
|
-
simulateBeforeSubmit?: boolean;
|
|
524
|
-
}
|
|
525
371
|
/**
|
|
526
|
-
*
|
|
527
|
-
*
|
|
528
|
-
* MintingGateway calls into `submitMintAndSwap()` after it has signed the
|
|
529
|
-
* MintRequest and verified the ReceiverConsent.
|
|
372
|
+
* Builds unsigned `PartialUserOperation` payloads for the v1.4 sponsored
|
|
373
|
+
* flow. The service is stateless and HTTP-client-free:
|
|
530
374
|
*
|
|
531
|
-
*
|
|
532
|
-
*
|
|
533
|
-
*
|
|
375
|
+
* - `prepareMint` signs a `MintRequest` EIP-712 with the caller-supplied
|
|
376
|
+
* issuer signer wallet, then encodes `PointToken.mint(to, amount,
|
|
377
|
+
* deadline, minterSig)` into a UserOp the frontend submits via
|
|
378
|
+
* EIP-7702 + Paymaster.
|
|
379
|
+
* - `prepareBurn` mirrors the above on the burn side using a
|
|
380
|
+
* pre-signed `BurnRequest` + `PointToken.burn(from, amount,
|
|
381
|
+
* deadline, burnerSig)`.
|
|
382
|
+
*
|
|
383
|
+
* There is no broadcasting, no operator wallet, no simulation — those
|
|
384
|
+
* concerns moved to the Bundler + Paymaster in v1.4.
|
|
534
385
|
*/
|
|
535
386
|
declare class RelayService {
|
|
536
|
-
private readonly relayAddress;
|
|
537
|
-
private readonly operatorWallet;
|
|
538
|
-
private readonly provider?;
|
|
539
|
-
private readonly confirmationTimeoutMs;
|
|
540
|
-
private readonly simulateBeforeSubmit;
|
|
541
|
-
constructor(config: RelayServiceConfig);
|
|
542
|
-
/** Address the operator wallet is broadcasting from (for logging). */
|
|
543
|
-
operatorAddress(): Address | undefined;
|
|
544
|
-
/**
|
|
545
|
-
* Build calldata for the Relay `mintAndSwap` function. Kept public so
|
|
546
|
-
* callers (e.g. the MintingGateway) can log or persist the encoded call
|
|
547
|
-
* for audit before broadcasting.
|
|
548
|
-
*/
|
|
549
|
-
encodeCall(params: SubmitMintAndSwapParams): Hex;
|
|
550
387
|
/**
|
|
551
|
-
*
|
|
552
|
-
*
|
|
553
|
-
* 1. (optional) pre-flight simulate via provider
|
|
554
|
-
* 2. writeContract through the operator wallet
|
|
555
|
-
* 3. (optional) wait for the receipt and surface gasUsed / status
|
|
556
|
-
*
|
|
557
|
-
* Throws a typed `RelayError` on any failure so the MintingGateway can
|
|
558
|
-
* decide whether to release the ledger lock (`SUBMIT_FAILED` and
|
|
559
|
-
* `SIMULATION_FAILED` are safe to release; `TX_REVERTED` and `TIMEOUT`
|
|
560
|
-
* need manual review because the tx may still land).
|
|
561
|
-
*
|
|
562
|
-
* @deprecated Since 0.3.0 — will be replaced by `prepareMint()` +
|
|
563
|
-
* `prepareBurn()` in the v1.4 sponsored-UserOp flow. The SC team
|
|
564
|
-
* still needs to finalize Relayer v2 ABI before the replacements
|
|
565
|
-
* can ship (blocker B1). Kept for v0.2.x consumers. Removed in 2.0.
|
|
388
|
+
* Build an unsigned UserOp for Scenario 1 (Mint) — sig-gated
|
|
389
|
+
* `PointToken.mint(to, amount, deadline, minterSig)`.
|
|
566
390
|
*/
|
|
567
|
-
|
|
568
|
-
/**
|
|
569
|
-
* Build an unsigned UserOp for Scenario 1 (Mint).
|
|
570
|
-
*
|
|
571
|
-
* Flow:
|
|
572
|
-
* 1. Encode `Relayer.mint(request, userSig, issuerSig)` as the inner call
|
|
573
|
-
* 2. Optionally append a PT fee transfer from user → feeRecipient
|
|
574
|
-
* (fee recovery happens on-chain via BatchExecutor, not via an
|
|
575
|
-
* operator wallet)
|
|
576
|
-
* 3. Wrap all inner calls into `BatchExecutor.execute(calls[])`
|
|
577
|
-
* 4. Return a `PartialUserOperation` ready for:
|
|
578
|
-
* - gas estimation (Bundler)
|
|
579
|
-
* - paymaster sponsorship (PAFI Backend)
|
|
580
|
-
* - user signature (Privy)
|
|
581
|
-
*/
|
|
582
|
-
prepareMint(params: PrepareMintParams): PartialUserOperation;
|
|
391
|
+
prepareMint(params: PrepareMintParams): Promise<PartialUserOperation>;
|
|
583
392
|
/**
|
|
584
393
|
* Build an unsigned UserOp for Scenario 2 (Burn/Redeem).
|
|
585
394
|
*
|
|
586
395
|
* Two modes:
|
|
587
|
-
* - `mode: 'burn'` — direct `PointToken.burn(amount)`;
|
|
588
|
-
* via EIP-7702
|
|
589
|
-
*
|
|
590
|
-
*
|
|
591
|
-
*
|
|
592
|
-
*
|
|
593
|
-
* contract has to do it on-chain
|
|
396
|
+
* - `mode: 'burn'` — direct `PointToken.burn(from, amount)`; only
|
|
397
|
+
* usable if the caller (via EIP-7702) is whitelisted as a burner.
|
|
398
|
+
* Rare in v1.4; kept for admin/operator tools.
|
|
399
|
+
* - `mode: 'burnWithSig'` — `PointToken.burn(from, amount, deadline,
|
|
400
|
+
* burnerSig)`. Caller provides a pre-signed `BurnRequest` + sig
|
|
401
|
+
* bytes (typically from `PTRedeemHandler`).
|
|
594
402
|
*/
|
|
595
403
|
prepareBurn(params: PrepareBurnParams): PartialUserOperation;
|
|
596
404
|
}
|
|
405
|
+
/**
|
|
406
|
+
* v1.4 — sig-gated `PointToken.mint(to, amount, deadline, minterSig)`.
|
|
407
|
+
*
|
|
408
|
+
* The issuer backend validates off-chain (balance, policy, KYC), signs
|
|
409
|
+
* a `MintRequest` EIP-712 with its minter signer, and packages the
|
|
410
|
+
* whole thing into a UserOp for the user to submit via EIP-7702 +
|
|
411
|
+
* Paymaster. On confirmation, PointIndexer watches `Transfer(0x0, user,
|
|
412
|
+
* amount)` and resolves the ledger lock.
|
|
413
|
+
*/
|
|
597
414
|
interface PrepareMintParams {
|
|
598
415
|
/** User EOA that will send the UserOp (via EIP-7702 delegation). */
|
|
599
416
|
userAddress: Address;
|
|
600
|
-
/** ERC-4337 account nonce
|
|
417
|
+
/** ERC-4337 account nonce. Caller fetches from EntryPoint v0.7. */
|
|
601
418
|
aaNonce: bigint;
|
|
602
|
-
/** Deployed Relayer v2 contract address (chain-specific). */
|
|
603
|
-
relayerAddress: Address;
|
|
604
419
|
/** BatchExecutor delegation target (chain-specific). */
|
|
605
420
|
batchExecutorAddress: Address;
|
|
606
|
-
/** PointToken
|
|
421
|
+
/** PointToken contract — the call target + EIP-712 verifying contract. */
|
|
607
422
|
pointTokenAddress: Address;
|
|
608
|
-
/**
|
|
609
|
-
|
|
610
|
-
/**
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
423
|
+
/** PT amount to mint to `userAddress`. */
|
|
424
|
+
amount: bigint;
|
|
425
|
+
/**
|
|
426
|
+
* Issuer minter signer wallet — signs the `MintRequest` EIP-712.
|
|
427
|
+
* Must be added to `PointToken.minters[]` via `addMinter(signerAddr)`
|
|
428
|
+
* at provisioning time. Typically HSM/KMS-backed in prod.
|
|
429
|
+
*/
|
|
430
|
+
issuerSignerWallet: WalletClient;
|
|
431
|
+
/** EIP-712 domain for MintRequest. */
|
|
432
|
+
domain: PointTokenDomainConfig;
|
|
433
|
+
/** Current `mintRequestNonces[userAddress]` — caller reads from contract. */
|
|
434
|
+
mintRequestNonce: bigint;
|
|
435
|
+
/** Unix timestamp after which the signature expires. */
|
|
436
|
+
deadline: bigint;
|
|
437
|
+
/**
|
|
438
|
+
* Optional — application-level fee transfer appended after mint.
|
|
439
|
+
* Set both `feeAmount` and `feeRecipient` together.
|
|
440
|
+
*/
|
|
441
|
+
feeAmount?: bigint;
|
|
442
|
+
feeRecipient?: Address;
|
|
614
443
|
/** Gas limits — defaults are conservative; caller can tighten. */
|
|
615
444
|
callGasLimit?: bigint;
|
|
616
445
|
verificationGasLimit?: bigint;
|
|
@@ -632,8 +461,10 @@ interface PrepareBurnDirectParams extends PrepareBurnCommonParams {
|
|
|
632
461
|
}
|
|
633
462
|
interface PrepareBurnWithSigParams extends PrepareBurnCommonParams {
|
|
634
463
|
mode: "burnWithSig";
|
|
635
|
-
|
|
636
|
-
|
|
464
|
+
/** BurnRequest message the issuer burner signer signed. */
|
|
465
|
+
burnRequest: BurnRequest;
|
|
466
|
+
/** Serialized EIP-712 signature (bytes) over `burnRequest`. */
|
|
467
|
+
burnerSignature: Hex;
|
|
637
468
|
}
|
|
638
469
|
|
|
639
470
|
interface FeeManagerConfig {
|
|
@@ -683,6 +514,9 @@ declare class FeeManager {
|
|
|
683
514
|
private readonly gasUnits;
|
|
684
515
|
private readonly gasPremiumBps;
|
|
685
516
|
private readonly quoteNativeToFee;
|
|
517
|
+
private cachedFee;
|
|
518
|
+
private cacheExpiresAt;
|
|
519
|
+
private static readonly CACHE_TTL_MS;
|
|
686
520
|
constructor(config: FeeManagerConfig);
|
|
687
521
|
/**
|
|
688
522
|
* Estimate the fee (in the caller's fee currency) to charge for the
|
|
@@ -699,156 +533,6 @@ declare class FeeManager {
|
|
|
699
533
|
estimateGasFee(): Promise<bigint>;
|
|
700
534
|
}
|
|
701
535
|
|
|
702
|
-
/**
|
|
703
|
-
* End-user request for a full "burn points → receive USDT" flow. The
|
|
704
|
-
* receiver has already signed the `ReceiverConsent` EIP-712 message on
|
|
705
|
-
* the frontend; the issuer backend runs everything else.
|
|
706
|
-
*/
|
|
707
|
-
interface MintAndCashOutRequest {
|
|
708
|
-
/** Address owning the off-chain points (== receiver in the consent). */
|
|
709
|
-
userAddress: Address;
|
|
710
|
-
/** Point token contract to mint. */
|
|
711
|
-
pointTokenAddress: Address;
|
|
712
|
-
/** Chain id the relay will submit on. */
|
|
713
|
-
chainId: number;
|
|
714
|
-
/**
|
|
715
|
-
* EIP-712 domain for `pointTokenAddress`. The gateway passes this
|
|
716
|
-
* straight through to `@pafi/core` `verifyReceiverConsent` and the
|
|
717
|
-
* issuer signer. Callers typically fetch it once via
|
|
718
|
-
* `PafiSDK.getDomain()` and cache it.
|
|
719
|
-
*/
|
|
720
|
-
domain: PointTokenDomainConfig;
|
|
721
|
-
/**
|
|
722
|
-
* Receiver consent message + signature, pre-built by the frontend. The
|
|
723
|
-
* message specifies `onBehalfOf = relay contract` and
|
|
724
|
-
* `originalReceiver = userAddress`, plus the amount, nonce, deadline,
|
|
725
|
-
* and encoded extData.
|
|
726
|
-
*/
|
|
727
|
-
receiverConsent: ReceiverConsent;
|
|
728
|
-
receiverSignature: Hex;
|
|
729
|
-
/**
|
|
730
|
-
* Swap path for the USDT output. Empty array = "no swap" (rare — only
|
|
731
|
-
* useful for testing). Normally a single hop pointToken → USDT.
|
|
732
|
-
*/
|
|
733
|
-
swapPath: PathKey[];
|
|
734
|
-
/** Swap deadline (unix seconds). */
|
|
735
|
-
swapDeadline: bigint;
|
|
736
|
-
/**
|
|
737
|
-
* Lock TTL (ms) to apply to the off-chain balance. The gateway computes
|
|
738
|
-
* a safe default from `receiverConsent.deadline` if omitted.
|
|
739
|
-
*/
|
|
740
|
-
lockDurationMs?: number;
|
|
741
|
-
}
|
|
742
|
-
/**
|
|
743
|
-
* Result returned to the caller after a successful `processMintAndCashOut`.
|
|
744
|
-
* The `lockId` is preserved so the indexer can correlate the on-chain
|
|
745
|
-
* Mint event back to the ledger row (though that correlation is typically
|
|
746
|
-
* done by `(userAddress, amount)` in the default `MemoryPointLedger`).
|
|
747
|
-
*/
|
|
748
|
-
interface MintAndCashOutResponse {
|
|
749
|
-
txHash: Hex;
|
|
750
|
-
lockId: string;
|
|
751
|
-
blockNumber?: bigint;
|
|
752
|
-
gasUsed?: bigint;
|
|
753
|
-
}
|
|
754
|
-
/**
|
|
755
|
-
* Error codes a MintingGateway can surface. Callers (API handlers) map
|
|
756
|
-
* these to HTTP status codes. The `SAFE_TO_RETRY` field tells the caller
|
|
757
|
-
* whether the underlying lock was released — if not, the user should
|
|
758
|
-
* wait before retrying to avoid double-spend.
|
|
759
|
-
*/
|
|
760
|
-
type MintingGatewayErrorCode = "INVALID_REQUEST" | "INVALID_CONSENT_SIGNATURE" | "CONSENT_EXPIRED" | "POLICY_REJECTED" | "INSUFFICIENT_BALANCE" | "SIGNER_FAILED" | "RELAY_SIMULATION_FAILED" | "RELAY_SUBMIT_FAILED" | "RELAY_REVERTED" | "RELAY_TIMEOUT";
|
|
761
|
-
declare class MintingGatewayError extends Error {
|
|
762
|
-
readonly code: MintingGatewayErrorCode;
|
|
763
|
-
/**
|
|
764
|
-
* True if the ledger lock was released before this error was thrown,
|
|
765
|
-
* meaning the user can safely retry. False means the funds are still
|
|
766
|
-
* locked (e.g. tx may still land on-chain) and retry would double-spend.
|
|
767
|
-
*/
|
|
768
|
-
readonly safeToRetry: boolean;
|
|
769
|
-
readonly cause?: unknown;
|
|
770
|
-
constructor(code: MintingGatewayErrorCode, message: string, opts: {
|
|
771
|
-
safeToRetry: boolean;
|
|
772
|
-
cause?: unknown;
|
|
773
|
-
});
|
|
774
|
-
}
|
|
775
|
-
|
|
776
|
-
interface MintingGatewayConfig {
|
|
777
|
-
ledger: IPointLedger;
|
|
778
|
-
policy: IPolicyEngine;
|
|
779
|
-
signer: IIssuerSigner;
|
|
780
|
-
relayService: RelayService;
|
|
781
|
-
/**
|
|
782
|
-
* Clock override for tests. Defaults to `() => Date.now()`. Used to
|
|
783
|
-
* compute safe lock TTLs and to check consent deadlines.
|
|
784
|
-
*/
|
|
785
|
-
now?: () => number;
|
|
786
|
-
/**
|
|
787
|
-
* Extra buffer (ms) added on top of `(consent.deadline - now)` when the
|
|
788
|
-
* caller doesn't supply a `lockDurationMs`. Default: 60_000 (one minute
|
|
789
|
-
* — roughly 2× the Base L2 block confirmation time).
|
|
790
|
-
*/
|
|
791
|
-
defaultLockBufferMs?: number;
|
|
792
|
-
}
|
|
793
|
-
/**
|
|
794
|
-
* The MintingGateway is the central orchestrator that turns a user's
|
|
795
|
-
* signed ReceiverConsent into an on-chain `mintAndSwap` tx and a
|
|
796
|
-
* consistent off-chain ledger update.
|
|
797
|
-
*
|
|
798
|
-
* 11-step flow (per `PAFI_ISSUER_SDK_SPEC.md` §4.3):
|
|
799
|
-
*
|
|
800
|
-
* 1. Field validation (cheap rejects before any crypto)
|
|
801
|
-
* 2. Verify ReceiverConsent signature via `@pafi/core`
|
|
802
|
-
* 3. Check off-chain balance via ledger
|
|
803
|
-
* 4. Check locked requests via ledger
|
|
804
|
-
* 5. Run policy engine (balance + on-chain cap + issuer rules)
|
|
805
|
-
* 6. Lock the requested amount in the ledger
|
|
806
|
-
* 7. Sign MintRequest as issuer
|
|
807
|
-
* 8. Build MintParams + SwapParams
|
|
808
|
-
* 9. Submit via RelayService (encode + simulate + broadcast + wait)
|
|
809
|
-
* 10. Return { txHash, lockId, receipt fields }
|
|
810
|
-
* 11. On any failure, release the lock IF it's safe to retry — i.e. we
|
|
811
|
-
* know the tx cannot still land on-chain. If the tx may have made
|
|
812
|
-
* it (`TX_REVERTED` or `TIMEOUT`), we leave the lock alone and
|
|
813
|
-
* surface `safeToRetry: false` so the caller doesn't double-spend.
|
|
814
|
-
*
|
|
815
|
-
* The gateway deliberately does NOT deduct the balance here. Deduction
|
|
816
|
-
* happens in the `PointIndexer` when the on-chain Mint event is observed,
|
|
817
|
-
* which is what makes the system crash-safe: if the gateway dies between
|
|
818
|
-
* broadcast and receipt, the indexer will still finalize the ledger.
|
|
819
|
-
*/
|
|
820
|
-
declare class MintingGateway {
|
|
821
|
-
private readonly ledger;
|
|
822
|
-
private readonly policy;
|
|
823
|
-
private readonly signer;
|
|
824
|
-
private readonly relayService;
|
|
825
|
-
private readonly now;
|
|
826
|
-
private readonly defaultLockBufferMs;
|
|
827
|
-
constructor(config: MintingGatewayConfig);
|
|
828
|
-
/**
|
|
829
|
-
* @deprecated Since 0.3.0 — will be renamed to `processMint()` once
|
|
830
|
-
* the SC team finalizes Relayer v2 ABI. The new flow drops the
|
|
831
|
-
* swap steps entirely (no more single-call mint+swap); users swap
|
|
832
|
-
* separately on PAFI Web. Kept here for v0.2.x consumers. Removed in 2.0.
|
|
833
|
-
*/
|
|
834
|
-
processMintAndCashOut(request: MintAndCashOutRequest): Promise<MintAndCashOutResponse>;
|
|
835
|
-
private computeLockDurationMs;
|
|
836
|
-
/**
|
|
837
|
-
* Map a RelayError to a MintingGatewayError, releasing the lock only
|
|
838
|
-
* when the tx definitely did not land. `TX_REVERTED` and `TIMEOUT`
|
|
839
|
-
* leave the lock in place because the tx may still be in the mempool
|
|
840
|
-
* or already mined — releasing would enable a double-spend on retry.
|
|
841
|
-
* Always throws.
|
|
842
|
-
*/
|
|
843
|
-
private handleRelayFailure;
|
|
844
|
-
/**
|
|
845
|
-
* Release a lock, swallowing any secondary error. We never want a lock
|
|
846
|
-
* release failure to mask the original error — the lock will auto-expire
|
|
847
|
-
* via TTL anyway.
|
|
848
|
-
*/
|
|
849
|
-
private releaseLockSafely;
|
|
850
|
-
}
|
|
851
|
-
|
|
852
536
|
/** Decoded Transfer(from=0x0 → to) event used to finalize a mint. */
|
|
853
537
|
interface MintEvent {
|
|
854
538
|
/** Destination address (the user who received the minted points) */
|
|
@@ -1008,6 +692,15 @@ interface BurnIndexerConfig {
|
|
|
1008
692
|
/** Polling interval (ms). Default: 5000. */
|
|
1009
693
|
pollIntervalMs?: number;
|
|
1010
694
|
now?: () => number;
|
|
695
|
+
/**
|
|
696
|
+
* Map a burn event to the pending credit lockId that should be resolved.
|
|
697
|
+
* Return `undefined` to skip this burn event (no credit granted).
|
|
698
|
+
*
|
|
699
|
+
* REQUIRED — there is no default implementation. Issuers with a Postgres
|
|
700
|
+
* ledger typically JOIN on `(from, amount, status=PENDING)`. The in-memory
|
|
701
|
+
* ledger uses a lookup by lockId supplied out-of-band from the claim flow.
|
|
702
|
+
*/
|
|
703
|
+
matchLockId: (event: BurnEvent) => Promise<string | undefined>;
|
|
1011
704
|
}
|
|
1012
705
|
/**
|
|
1013
706
|
* Mirror of `PointIndexer` for the reverse direction — watches
|
|
@@ -1038,17 +731,6 @@ declare class BurnIndexer {
|
|
|
1038
731
|
private readonly confirmations;
|
|
1039
732
|
private readonly batchSize;
|
|
1040
733
|
private readonly pollIntervalMs;
|
|
1041
|
-
/**
|
|
1042
|
-
* Caller-supplied matcher. Return the lockId to resolve for a given
|
|
1043
|
-
* burn event, or `undefined` to skip. Runs synchronously via the
|
|
1044
|
-
* ledger's query path.
|
|
1045
|
-
*
|
|
1046
|
-
* Default: try `ledger.resolveCreditByBurnTx` keyed on a synthetic
|
|
1047
|
-
* lock id `burn-${from}-${amount}` — the in-memory ledger assigns
|
|
1048
|
-
* incrementing IDs so callers with the memory ledger must provide a
|
|
1049
|
-
* custom matcher. Real DB-backed ledgers override this to JOIN on
|
|
1050
|
-
* their `pending_credits` table.
|
|
1051
|
-
*/
|
|
1052
734
|
matchLockId: (event: BurnEvent) => Promise<string | undefined>;
|
|
1053
735
|
private running;
|
|
1054
736
|
private timer;
|
|
@@ -1093,6 +775,18 @@ interface ApiConfigResponse {
|
|
|
1093
775
|
mintingOracle?: Address;
|
|
1094
776
|
poolManager?: Address;
|
|
1095
777
|
usdt?: Address;
|
|
778
|
+
/**
|
|
779
|
+
* EIP-7702 delegation target — the single contract every user's
|
|
780
|
+
* EOA must delegate to before submitting sponsored UserOps. On
|
|
781
|
+
* Base mainnet this is Coinbase Smart Wallet v2.
|
|
782
|
+
*/
|
|
783
|
+
batchExecutor?: Address;
|
|
784
|
+
/**
|
|
785
|
+
* Uniswap V4 hook that enforces the 10% fee on PT→USDT swaps
|
|
786
|
+
* (USDT→PT is free). FE uses this in `PoolKey.hooks` when building
|
|
787
|
+
* a swap; the pool is only discoverable when the hook matches.
|
|
788
|
+
*/
|
|
789
|
+
pafiHook?: Address;
|
|
1096
790
|
};
|
|
1097
791
|
/**
|
|
1098
792
|
* Absolute URL that the Issuer App opens after a successful claim to
|
|
@@ -1186,6 +880,27 @@ interface ApiClaimAndSwapResponse {
|
|
|
1186
880
|
blockNumber?: bigint;
|
|
1187
881
|
gasUsed?: bigint;
|
|
1188
882
|
}
|
|
883
|
+
interface ApiClaimRequest {
|
|
884
|
+
chainId: number;
|
|
885
|
+
pointTokenAddress: Address;
|
|
886
|
+
/** PT amount to mint. */
|
|
887
|
+
amount: bigint;
|
|
888
|
+
/** ERC-4337 account nonce for the user's EOA (from EntryPoint). */
|
|
889
|
+
aaNonce: bigint;
|
|
890
|
+
/** Unix seconds — when the MintRequest signature expires. */
|
|
891
|
+
deadline: bigint;
|
|
892
|
+
/** Optional operator fee (PT) deducted inside the same UserOp batch. */
|
|
893
|
+
feeAmount?: bigint;
|
|
894
|
+
feeRecipient?: Address;
|
|
895
|
+
}
|
|
896
|
+
interface ApiClaimResponse {
|
|
897
|
+
/** Off-chain lock id — poll `/user` to track PENDING → MINTED. */
|
|
898
|
+
lockId: string;
|
|
899
|
+
/** Unsigned UserOp — attach paymaster data + user signature, then submit. */
|
|
900
|
+
userOp: PartialUserOperation;
|
|
901
|
+
/** Seconds until the off-chain lock expires if the UserOp is not submitted. */
|
|
902
|
+
expiresInSeconds: number;
|
|
903
|
+
}
|
|
1189
904
|
interface ApiBuildConsentTypedDataRequest {
|
|
1190
905
|
chainId: number;
|
|
1191
906
|
pointTokenAddress: Address;
|
|
@@ -1211,7 +926,6 @@ type PoolsProvider = (request: ApiPoolsRequest) => Promise<ApiPoolsResponse>;
|
|
|
1211
926
|
|
|
1212
927
|
interface IssuerApiHandlersConfig {
|
|
1213
928
|
authService: AuthService;
|
|
1214
|
-
gateway: MintingGateway;
|
|
1215
929
|
ledger: IPointLedger;
|
|
1216
930
|
/** Used by `handleUser` to read on-chain nonces and minter status. */
|
|
1217
931
|
provider: PublicClient;
|
|
@@ -1237,13 +951,26 @@ interface IssuerApiHandlersConfig {
|
|
|
1237
951
|
feeManager?: FeeManager;
|
|
1238
952
|
/** Required by `handlePools`; omit to disable the endpoint. */
|
|
1239
953
|
poolsProvider?: PoolsProvider;
|
|
954
|
+
/**
|
|
955
|
+
* Required by `handleClaim`; omit to disable the endpoint.
|
|
956
|
+
* Wires policy evaluation + ledger locking + MintRequest signing
|
|
957
|
+
* into a single atomic handler so callers cannot accidentally skip
|
|
958
|
+
* the policy check.
|
|
959
|
+
*/
|
|
960
|
+
claim?: {
|
|
961
|
+
policy: IPolicyEngine;
|
|
962
|
+
relayService: RelayService;
|
|
963
|
+
issuerSignerWallet: WalletClient;
|
|
964
|
+
batchExecutorAddress: Address;
|
|
965
|
+
/** How long to hold the off-chain lock while the UserOp is in flight. Default: 15 min. */
|
|
966
|
+
lockDurationMs?: number;
|
|
967
|
+
};
|
|
1240
968
|
}
|
|
1241
969
|
/**
|
|
1242
970
|
* Framework-agnostic HTTP handlers that match the endpoints a `PafiSDK`
|
|
1243
971
|
* frontend expects to call. Issuers wrap these in Express / Fastify /
|
|
1244
972
|
* Hono / whatever — the handlers take plain inputs and return plain
|
|
1245
|
-
* outputs, with `AuthError`
|
|
1246
|
-
* exceptions.
|
|
973
|
+
* outputs, with `AuthError` surfaced as typed exceptions.
|
|
1247
974
|
*
|
|
1248
975
|
* Every protected handler takes a pre-verified `userAddress` as its first
|
|
1249
976
|
* argument. The issuer's middleware wraps `authenticateRequest()` from
|
|
@@ -1252,7 +979,6 @@ interface IssuerApiHandlersConfig {
|
|
|
1252
979
|
*/
|
|
1253
980
|
declare class IssuerApiHandlers {
|
|
1254
981
|
private readonly authService;
|
|
1255
|
-
private readonly gateway;
|
|
1256
982
|
private readonly ledger;
|
|
1257
983
|
private readonly provider;
|
|
1258
984
|
/**
|
|
@@ -1260,15 +986,12 @@ declare class IssuerApiHandlers {
|
|
|
1260
986
|
* validate the request's `pointTokenAddress` against this set.
|
|
1261
987
|
*/
|
|
1262
988
|
private readonly supportedTokens;
|
|
1263
|
-
/** First supported token — used as default when a handler doesn't
|
|
1264
|
-
* receive a `pointTokenAddress` in the request (shouldn't happen in
|
|
1265
|
-
* practice, but keeps type-narrowing happy). */
|
|
1266
|
-
private readonly defaultToken;
|
|
1267
989
|
private readonly chainId;
|
|
1268
990
|
private readonly contracts;
|
|
1269
991
|
private readonly pafiWebUrl?;
|
|
1270
992
|
private readonly feeManager?;
|
|
1271
993
|
private readonly poolsProvider?;
|
|
994
|
+
private readonly claim?;
|
|
1272
995
|
constructor(config: IssuerApiHandlersConfig);
|
|
1273
996
|
/** `GET /auth/nonce` */
|
|
1274
997
|
handleGetNonce(): Promise<ApiNonceResponse>;
|
|
@@ -1315,32 +1038,47 @@ declare class IssuerApiHandlers {
|
|
|
1315
1038
|
*/
|
|
1316
1039
|
handleBuildConsentTypedData(userAddress: Address, request: ApiBuildConsentTypedDataRequest): Promise<ApiBuildConsentTypedDataResponse>;
|
|
1317
1040
|
/**
|
|
1318
|
-
* `POST /claim
|
|
1041
|
+
* `POST /claim`
|
|
1319
1042
|
*
|
|
1320
|
-
*
|
|
1321
|
-
*
|
|
1322
|
-
*
|
|
1323
|
-
* [V1.4_V1.5_OVERVIEW.md §4] for the new scenario model. Will be
|
|
1324
|
-
* removed in 2.0.
|
|
1043
|
+
* Policy gate + ledger lock + MintRequest signing in a single atomic
|
|
1044
|
+
* step. Returns an unsigned UserOp the frontend attaches paymaster data
|
|
1045
|
+
* to and submits via EIP-7702 + Bundler.
|
|
1325
1046
|
*
|
|
1326
|
-
*
|
|
1327
|
-
*
|
|
1047
|
+
* Order of operations:
|
|
1048
|
+
* 1. Validate request fields.
|
|
1049
|
+
* 2. policy.evaluate() — throws if denied; cannot be bypassed.
|
|
1050
|
+
* 3. ledger.lockForMinting() — reserves the balance.
|
|
1051
|
+
* 4. Read on-chain mintRequestNonce + token name in parallel.
|
|
1052
|
+
* 5. relayService.prepareMint() — sign MintRequest + encode UserOp.
|
|
1053
|
+
* 6. On any error after step 3, release the lock before re-throwing.
|
|
1328
1054
|
*/
|
|
1329
|
-
|
|
1055
|
+
handleClaim(userAddress: Address, request: ApiClaimRequest): Promise<ApiClaimResponse>;
|
|
1330
1056
|
}
|
|
1331
1057
|
|
|
1332
1058
|
/**
|
|
1333
|
-
* v1.4 reverse flow —
|
|
1059
|
+
* v1.4 reverse flow — user-initiated PT redeem.
|
|
1334
1060
|
*
|
|
1335
|
-
* User has on-chain PT, wants to convert back to off-chain points.
|
|
1336
|
-
*
|
|
1337
|
-
* off-chain credit, and returns an unsigned UserOp
|
|
1338
|
-
* submits via
|
|
1339
|
-
* (
|
|
1061
|
+
* User has on-chain PT, wants to convert back to off-chain points. The
|
|
1062
|
+
* issuer backend signs a `BurnRequest` with its burner signer, reserves
|
|
1063
|
+
* an off-chain pending credit, and returns an unsigned UserOp. The FE
|
|
1064
|
+
* submits the UserOp via EIP-7702 + Coinbase Paymaster. On confirmation,
|
|
1065
|
+
* `Transfer(user → 0x0)` is emitted; `BurnIndexer` resolves the pending
|
|
1066
|
+
* credit to a real off-chain credit.
|
|
1340
1067
|
*
|
|
1341
|
-
*
|
|
1342
|
-
*
|
|
1343
|
-
*
|
|
1068
|
+
* Contract path (mock ABI — matches deployed PointToken):
|
|
1069
|
+
*
|
|
1070
|
+
* burn(address from, uint256 amount, uint256 deadline, bytes burnerSig)
|
|
1071
|
+
*
|
|
1072
|
+
* On-chain checks:
|
|
1073
|
+
* - msg.sender == from (enforced via EIP-7702 delegation on user EOA)
|
|
1074
|
+
* - burnerSig signer ∈ burners[]
|
|
1075
|
+
* - nonce == burnRequestNonces[from]
|
|
1076
|
+
* - now <= deadline
|
|
1077
|
+
*
|
|
1078
|
+
* The user never signs an EIP-712 message in this flow. Their only
|
|
1079
|
+
* signature is the ERC-4337 UserOp signature, which the AA wallet
|
|
1080
|
+
* handles. Consent is implicit: by submitting the UserOp they authorize
|
|
1081
|
+
* the burn.
|
|
1344
1082
|
*/
|
|
1345
1083
|
interface PTRedeemHandlerConfig {
|
|
1346
1084
|
ledger: IPointLedger;
|
|
@@ -1350,32 +1088,43 @@ interface PTRedeemHandlerConfig {
|
|
|
1350
1088
|
pointTokenAddress: Address;
|
|
1351
1089
|
/** BatchExecutor delegation target (chain-specific). */
|
|
1352
1090
|
batchExecutorAddress: Address;
|
|
1353
|
-
/** Chain id — used for
|
|
1091
|
+
/** Chain id — used for the BurnRequest EIP-712 domain. */
|
|
1354
1092
|
chainId: number;
|
|
1355
1093
|
/**
|
|
1356
1094
|
* EIP-712 domain fields. Must match the on-chain PointToken's domain
|
|
1357
|
-
* separator
|
|
1358
|
-
* typically the PointToken's ERC-20 name
|
|
1359
|
-
*
|
|
1095
|
+
* separator, or on-chain signature recovery fails. `name` is
|
|
1096
|
+
* typically the PointToken's ERC-20 name. `verifyingContract`
|
|
1097
|
+
* defaults to `pointTokenAddress`.
|
|
1360
1098
|
*/
|
|
1361
1099
|
domain: {
|
|
1362
1100
|
name: string;
|
|
1363
1101
|
verifyingContract?: Address;
|
|
1364
1102
|
};
|
|
1103
|
+
/**
|
|
1104
|
+
* Issuer burner signer wallet — signs the `BurnRequest` EIP-712.
|
|
1105
|
+
* Must be whitelisted via `PointToken.addBurner(signerAddr)` at
|
|
1106
|
+
* provisioning time. Typically HSM/KMS-backed in prod.
|
|
1107
|
+
*/
|
|
1108
|
+
burnerSignerWallet: WalletClient;
|
|
1365
1109
|
/**
|
|
1366
1110
|
* How long the pending credit stays reserved if the burn never lands.
|
|
1367
1111
|
* Default: 15 min — long enough for a bundler submission + confirmation.
|
|
1368
1112
|
*/
|
|
1369
1113
|
redeemLockDurationMs?: number;
|
|
1114
|
+
/**
|
|
1115
|
+
* How far ahead of `now` to set the BurnRequest deadline. Default:
|
|
1116
|
+
* 15 min. Must be long enough for Bundler + EntryPoint to execute;
|
|
1117
|
+
* short enough to prevent replay if the UserOp is abandoned.
|
|
1118
|
+
*/
|
|
1119
|
+
signatureDeadlineSeconds?: number;
|
|
1370
1120
|
/** Clock injection for tests; defaults to `Date.now`. */
|
|
1371
1121
|
now?: () => number;
|
|
1372
1122
|
}
|
|
1373
1123
|
interface PTRedeemRequest {
|
|
1124
|
+
/** Address extracted from the verified JWT — must match `userAddress`. */
|
|
1125
|
+
authenticatedAddress: Address;
|
|
1374
1126
|
userAddress: Address;
|
|
1375
1127
|
amount: bigint;
|
|
1376
|
-
/** Serialized EIP-712 signature over the BurnConsent. */
|
|
1377
|
-
consentSignature: Hex;
|
|
1378
|
-
consent: BurnConsent;
|
|
1379
1128
|
/** ERC-4337 account nonce for the user's EOA. */
|
|
1380
1129
|
aaNonce: bigint;
|
|
1381
1130
|
}
|
|
@@ -1386,19 +1135,24 @@ interface PTRedeemResponse {
|
|
|
1386
1135
|
userOp: PartialUserOperation;
|
|
1387
1136
|
/** Seconds until the lock expires if the burn doesn't land. */
|
|
1388
1137
|
expiresInSeconds: number;
|
|
1138
|
+
/** The BurnRequest deadline (unix seconds) — FE uses this to surface a countdown. */
|
|
1139
|
+
signatureDeadline: bigint;
|
|
1389
1140
|
}
|
|
1390
1141
|
declare class PTRedeemError extends Error {
|
|
1391
|
-
code: "
|
|
1392
|
-
constructor(code: "
|
|
1142
|
+
code: "UNAUTHORIZED" | "INVALID_AMOUNT" | "NONCE_READ_FAILED" | "LEDGER_NOT_SUPPORTED" | "SIGNING_FAILED";
|
|
1143
|
+
constructor(code: "UNAUTHORIZED" | "INVALID_AMOUNT" | "NONCE_READ_FAILED" | "LEDGER_NOT_SUPPORTED" | "SIGNING_FAILED", message: string);
|
|
1393
1144
|
}
|
|
1394
1145
|
declare class PTRedeemHandler {
|
|
1395
1146
|
private readonly ledger;
|
|
1396
1147
|
private readonly relayService;
|
|
1148
|
+
private readonly provider;
|
|
1397
1149
|
private readonly pointTokenAddress;
|
|
1398
1150
|
private readonly batchExecutorAddress;
|
|
1399
1151
|
private readonly chainId;
|
|
1400
1152
|
private readonly domain;
|
|
1153
|
+
private readonly burnerSignerWallet;
|
|
1401
1154
|
private readonly redeemLockDurationMs;
|
|
1155
|
+
private readonly signatureDeadlineSeconds;
|
|
1402
1156
|
private readonly now;
|
|
1403
1157
|
constructor(config: PTRedeemHandlerConfig);
|
|
1404
1158
|
handle(request: PTRedeemRequest): Promise<PTRedeemResponse>;
|
|
@@ -1419,8 +1173,12 @@ declare class PTRedeemHandler {
|
|
|
1419
1173
|
* → burn 200 PT, credit 200 off-chain, voucher proceeds with 500
|
|
1420
1174
|
*
|
|
1421
1175
|
* Delegates the actual burn construction to {@link PTRedeemHandler}
|
|
1422
|
-
* — this handler is pure business logic (
|
|
1423
|
-
*
|
|
1176
|
+
* — this handler is pure business logic (shortfall math + on-chain
|
|
1177
|
+
* balance check) on top.
|
|
1178
|
+
*
|
|
1179
|
+
* v1.4 note: user no longer pre-signs a `BurnConsent`. The issuer
|
|
1180
|
+
* backend signs a `BurnRequest` itself (see `PTRedeemHandler`), so
|
|
1181
|
+
* this handler only needs `userAddress + requiredAmount + aaNonce`.
|
|
1424
1182
|
*/
|
|
1425
1183
|
interface TopUpRedemptionHandlerConfig {
|
|
1426
1184
|
ledger: IPointLedger;
|
|
@@ -1430,15 +1188,13 @@ interface TopUpRedemptionHandlerConfig {
|
|
|
1430
1188
|
pointTokenAddress: Address;
|
|
1431
1189
|
}
|
|
1432
1190
|
interface TopUpRedemptionRequest {
|
|
1191
|
+
/** Address extracted from the verified JWT — must match `userAddress`. */
|
|
1192
|
+
authenticatedAddress: Address;
|
|
1433
1193
|
userAddress: Address;
|
|
1434
1194
|
/** Total points the voucher redemption requires off-chain. */
|
|
1435
1195
|
requiredAmount: bigint;
|
|
1436
|
-
/**
|
|
1437
|
-
|
|
1438
|
-
* with amount set to a worst-case upper bound. Handler inspects the
|
|
1439
|
-
* shortfall and uses the consent if the shortfall ≤ consent.amount.
|
|
1440
|
-
*/
|
|
1441
|
-
redeemRequest: Pick<PTRedeemRequest, "consent" | "consentSignature" | "aaNonce">;
|
|
1196
|
+
/** ERC-4337 account nonce for the user's EOA. */
|
|
1197
|
+
aaNonce: bigint;
|
|
1442
1198
|
}
|
|
1443
1199
|
type TopUpRedemptionResponse = {
|
|
1444
1200
|
action: "NO_TOP_UP_NEEDED";
|
|
@@ -1454,8 +1210,8 @@ type TopUpRedemptionResponse = {
|
|
|
1454
1210
|
redeem: PTRedeemResponse;
|
|
1455
1211
|
};
|
|
1456
1212
|
declare class TopUpRedemptionError extends Error {
|
|
1457
|
-
code: "
|
|
1458
|
-
constructor(code: "
|
|
1213
|
+
code: "UNAUTHORIZED" | "INSUFFICIENT_ONCHAIN_BALANCE" | "LEDGER_NOT_SUPPORTED";
|
|
1214
|
+
constructor(code: "UNAUTHORIZED" | "INSUFFICIENT_ONCHAIN_BALANCE" | "LEDGER_NOT_SUPPORTED", message: string);
|
|
1459
1215
|
}
|
|
1460
1216
|
declare class TopUpRedemptionHandler {
|
|
1461
1217
|
private readonly ledger;
|
|
@@ -1640,185 +1396,52 @@ declare class BalanceAggregator {
|
|
|
1640
1396
|
}
|
|
1641
1397
|
|
|
1642
1398
|
interface RetryConfig {
|
|
1643
|
-
/**
|
|
1644
|
-
* Max total attempts including the first try. Default: 1 (no retry).
|
|
1645
|
-
* Set to 3 to get 2 retries after the initial call.
|
|
1646
|
-
*
|
|
1647
|
-
* Only applies when the server error body carries `safeToRetry: true`
|
|
1648
|
-
* or the failure is a transient network/timeout error.
|
|
1649
|
-
*/
|
|
1650
1399
|
maxAttempts?: number;
|
|
1651
|
-
/**
|
|
1652
|
-
* Initial backoff delay in ms. Default: 500. Each subsequent retry
|
|
1653
|
-
* doubles this (exponential backoff) and adds ±20% jitter.
|
|
1654
|
-
*/
|
|
1655
1400
|
initialDelayMs?: number;
|
|
1656
|
-
/**
|
|
1657
|
-
* Hard ceiling for a single backoff (ms). Default: 10_000.
|
|
1658
|
-
*/
|
|
1659
1401
|
maxDelayMs?: number;
|
|
1660
|
-
/**
|
|
1661
|
-
* Upper bound on `retryAfter` from the server. If the server asks us
|
|
1662
|
-
* to wait longer than this (e.g. rate limit until UTC midnight), the
|
|
1663
|
-
* client gives up rather than blocking. Default: 30_000.
|
|
1664
|
-
*/
|
|
1665
1402
|
maxRetryAfterMs?: number;
|
|
1666
1403
|
}
|
|
1667
1404
|
interface PafiBackendConfig {
|
|
1668
|
-
/**
|
|
1669
|
-
* PAFI Backend API base URL. Example:
|
|
1670
|
-
* https://api.pacificfinance.org
|
|
1671
|
-
* https://staging-api.pacificfinance.org
|
|
1672
|
-
*/
|
|
1673
1405
|
url: string;
|
|
1674
|
-
/** PAFI-assigned issuer ID (e.g., "gg56"). Sent in X-Issuer-Id header. */
|
|
1675
1406
|
issuerId: string;
|
|
1676
|
-
/** Per-issuer API key (or JWT) for the Authorization header. */
|
|
1677
1407
|
apiKey: string;
|
|
1678
|
-
/** Optional fetch override for tests. */
|
|
1679
1408
|
fetchImpl?: typeof fetch;
|
|
1680
|
-
/**
|
|
1681
|
-
* Timeout (ms) for each request. Default: 10_000. PAFI Backend should
|
|
1682
|
-
* respond in <1s for the happy path; this is just the sanity bound.
|
|
1683
|
-
*/
|
|
1684
1409
|
timeoutMs?: number;
|
|
1685
|
-
/**
|
|
1686
|
-
* Retry policy for transient failures (5xx, 429, timeouts, network).
|
|
1687
|
-
* Omit or pass `{ maxAttempts: 1 }` to disable retry entirely.
|
|
1688
|
-
*/
|
|
1689
1410
|
retry?: RetryConfig;
|
|
1690
1411
|
}
|
|
1691
|
-
|
|
1692
|
-
interface SponsorshipRequest {
|
|
1693
|
-
chainId: number;
|
|
1694
|
-
scenario: SponsorshipScenario;
|
|
1695
|
-
userOp: PartialUserOperation;
|
|
1696
|
-
target: {
|
|
1697
|
-
/** The allowlisted contract this batch call targets. */
|
|
1698
|
-
contract: Address;
|
|
1699
|
-
/** Function selector / name — validated against allowlist. */
|
|
1700
|
-
function: string;
|
|
1701
|
-
/** The PointToken involved (for scenario context). */
|
|
1702
|
-
pointToken?: Address;
|
|
1703
|
-
};
|
|
1704
|
-
}
|
|
1705
|
-
interface SponsorshipResponse {
|
|
1706
|
-
paymaster: Address;
|
|
1707
|
-
paymasterData: Hex;
|
|
1708
|
-
paymasterVerificationGasLimit: bigint;
|
|
1709
|
-
paymasterPostOpGasLimit: bigint;
|
|
1710
|
-
/** Unix seconds when this sponsorship expires. Re-request after. */
|
|
1711
|
-
expiresAt: number;
|
|
1712
|
-
}
|
|
1713
|
-
/**
|
|
1714
|
-
* Machine-readable error codes returned by PAFI Backend.
|
|
1715
|
-
*
|
|
1716
|
-
* Source of truth: `apps/paymaster-proxy` `CalldataValidationError`,
|
|
1717
|
-
* `RateLimitError`, `CoinbaseClientError`. Keep in sync.
|
|
1718
|
-
*/
|
|
1719
|
-
type PafiBackendErrorCode = "MISSING_ISSUER_ID" | "MISSING_API_KEY" | "ISSUER_UNAUTHORIZED" | "CALLDATA_INVALID" | "CALLDATA_EMPTY_BATCH" | "TARGET_NOT_ALLOWLISTED" | "FUNCTION_NOT_ALLOWED" | "SCENARIO_MISMATCH" | "SCENARIO_DISABLED" | "RATE_LIMIT_EXCEEDED" | "RATE_LIMIT_EXCEEDED_DAILY" | "RATE_LIMIT_EXCEEDED_PER_USER" | "RATE_LIMITER_UNAVAILABLE" | "PAYMASTER_REJECTED" | "PAYMASTER_UNAVAILABLE" | "PAYMASTER_TIMEOUT" | "BAD_REQUEST" | "INTERNAL_ERROR" | "TIMEOUT" | "NETWORK_ERROR";
|
|
1412
|
+
type PafiBackendErrorCode = "MISSING_ISSUER_ID" | "MISSING_API_KEY" | "ISSUER_UNAUTHORIZED" | "USER_UNAUTHORIZED" | "INTENT_REJECTED" | "MINT_CAP_EXCEEDED" | "ISSUER_INACTIVE" | "BROKER_NOT_WHITELISTED" | "RATE_LIMIT_EXCEEDED" | "RATE_LIMIT_EXCEEDED_DAILY" | "RATE_LIMIT_EXCEEDED_PER_USER" | "ISSUER_BUDGET_EXCEEDED" | "RATE_LIMITER_UNAVAILABLE" | "BAD_REQUEST" | "INTERNAL_ERROR" | "TIMEOUT" | "NETWORK_ERROR";
|
|
1720
1413
|
declare class PafiBackendError extends Error {
|
|
1721
1414
|
code: PafiBackendErrorCode;
|
|
1722
1415
|
httpStatus: number;
|
|
1723
1416
|
details?: unknown | undefined;
|
|
1724
|
-
/**
|
|
1725
|
-
* Seconds to wait before retry. Populated from the server body
|
|
1726
|
-
* (e.g. rate limit returns the number of seconds until UTC midnight).
|
|
1727
|
-
*/
|
|
1728
1417
|
readonly retryAfter?: number;
|
|
1729
|
-
/**
|
|
1730
|
-
* `safeToRetry` as reported by the server body. Prefer this over the
|
|
1731
|
-
* code-based heuristic when available — the server knows more about
|
|
1732
|
-
* whether the same request will succeed on retry.
|
|
1733
|
-
*/
|
|
1734
1418
|
private readonly serverSafeToRetry?;
|
|
1735
1419
|
constructor(code: PafiBackendErrorCode, message: string, httpStatus: number, details?: unknown | undefined, opts?: {
|
|
1736
1420
|
retryAfter?: number;
|
|
1737
1421
|
safeToRetry?: boolean;
|
|
1738
1422
|
});
|
|
1739
|
-
/**
|
|
1740
|
-
* Whether the caller can safely retry the same request.
|
|
1741
|
-
*
|
|
1742
|
-
* If the server provided `safeToRetry` in the body, trust that.
|
|
1743
|
-
* Otherwise fall back to a code-based heuristic.
|
|
1744
|
-
*/
|
|
1745
1423
|
get safeToRetry(): boolean;
|
|
1746
1424
|
}
|
|
1747
1425
|
|
|
1748
1426
|
/**
|
|
1749
|
-
*
|
|
1750
|
-
* [SPONSORED_PATH_FLOW.md] for the full flow + API contract.
|
|
1427
|
+
* Top-level configuration for `createIssuerService`.
|
|
1751
1428
|
*
|
|
1752
|
-
*
|
|
1753
|
-
*
|
|
1754
|
-
*
|
|
1755
|
-
|
|
1756
|
-
declare class PafiBackendClient {
|
|
1757
|
-
private readonly url;
|
|
1758
|
-
private readonly issuerId;
|
|
1759
|
-
private readonly apiKey;
|
|
1760
|
-
private readonly fetchImpl;
|
|
1761
|
-
private readonly timeoutMs;
|
|
1762
|
-
private readonly retry;
|
|
1763
|
-
constructor(config: PafiBackendConfig);
|
|
1764
|
-
/**
|
|
1765
|
-
* Request paymaster sponsorship for a pre-built UserOperation.
|
|
1766
|
-
* See [SPONSORED_PATH_FLOW.md §4.1] for the API contract.
|
|
1767
|
-
*
|
|
1768
|
-
* Retries automatically on transient failures (5xx, timeouts, network
|
|
1769
|
-
* errors, and errors the server flags with `safeToRetry: true`) up to
|
|
1770
|
-
* `retry.maxAttempts`. 4xx errors that are not `safeToRetry` fail fast.
|
|
1771
|
-
*
|
|
1772
|
-
* @throws PafiBackendError on final failure after exhausting retries
|
|
1773
|
-
*/
|
|
1774
|
-
requestSponsorship(req: SponsorshipRequest): Promise<SponsorshipResponse>;
|
|
1775
|
-
private postWithRetry;
|
|
1776
|
-
/**
|
|
1777
|
-
* Pick the delay before the next retry.
|
|
1778
|
-
* - If the server sent `retryAfter` (seconds), honor it (capped by
|
|
1779
|
-
* `maxRetryAfterMs`) — returns null if the server wait exceeds the
|
|
1780
|
-
* cap, signalling the caller should give up.
|
|
1781
|
-
* - Otherwise: exponential backoff with ±20% jitter, capped at
|
|
1782
|
-
* `maxDelayMs`.
|
|
1783
|
-
*/
|
|
1784
|
-
private computeBackoff;
|
|
1785
|
-
private sleep;
|
|
1786
|
-
private post;
|
|
1787
|
-
/** JSON replacer that stringifies bigints. Paired with bigintReviver. */
|
|
1788
|
-
private bigintReplacer;
|
|
1789
|
-
/**
|
|
1790
|
-
* JSON reviver that coerces specific numeric-string fields back to
|
|
1791
|
-
* bigint. The server must send these fields as decimal strings.
|
|
1792
|
-
*/
|
|
1793
|
-
private bigintReviver;
|
|
1794
|
-
}
|
|
1795
|
-
|
|
1796
|
-
/**
|
|
1797
|
-
* Top-level configuration for `createIssuerService`. Everything except
|
|
1798
|
-
* the chain metadata, wallets, auth secret, and `signer` is optional and
|
|
1799
|
-
* falls back to the in-memory dev defaults — that makes the happy path
|
|
1800
|
-
* a single-call wire-up while still letting production issuers plug in
|
|
1801
|
-
* their own ledger, session store, policy engine, and KMS signer.
|
|
1429
|
+
* In v1.4 the SDK is HTTP-client-free: it signs EIP-712 messages, reads
|
|
1430
|
+
* on-chain state, builds unsigned UserOperations, and maintains the
|
|
1431
|
+
* off-chain ledger. It never broadcasts transactions — that's the
|
|
1432
|
+
* frontend's responsibility via Bundler + Paymaster.
|
|
1802
1433
|
*
|
|
1803
|
-
* **Multi-token (0.2.0):** Pass `pointTokenAddresses: Address[]` to
|
|
1434
|
+
* **Multi-token (0.2.0+):** Pass `pointTokenAddresses: Address[]` to
|
|
1804
1435
|
* support multiple PointTokens under a single issuer backend. Legacy
|
|
1805
1436
|
* `pointTokenAddress: Address` still works for single-token deployments.
|
|
1806
1437
|
* When both are provided, `pointTokenAddresses` takes precedence.
|
|
1807
1438
|
*/
|
|
1808
1439
|
interface IssuerServiceConfig {
|
|
1809
1440
|
chainId: number;
|
|
1810
|
-
/**
|
|
1811
|
-
* Address of the deployed PointToken. Legacy single-token shortcut;
|
|
1812
|
-
* prefer `pointTokenAddresses` for multi-token issuers.
|
|
1813
|
-
*/
|
|
1441
|
+
/** Legacy single-token shortcut; prefer `pointTokenAddresses`. */
|
|
1814
1442
|
pointTokenAddress?: Address;
|
|
1815
|
-
/**
|
|
1816
|
-
* All PointToken addresses this issuer supports. Takes precedence over
|
|
1817
|
-
* `pointTokenAddress`. Factory creates one `PointIndexer` per address.
|
|
1818
|
-
*/
|
|
1443
|
+
/** All PointToken addresses this issuer supports. */
|
|
1819
1444
|
pointTokenAddresses?: Address[];
|
|
1820
|
-
/** Address of the deployed Relay contract. */
|
|
1821
|
-
relayAddress: Address;
|
|
1822
1445
|
/**
|
|
1823
1446
|
* Full contract address bundle returned verbatim by `handleConfig` so
|
|
1824
1447
|
* the frontend SDK can pick them up.
|
|
@@ -1829,8 +1452,6 @@ interface IssuerServiceConfig {
|
|
|
1829
1452
|
* polling, and gas-price lookups. Must be pointed at the target chain.
|
|
1830
1453
|
*/
|
|
1831
1454
|
provider: PublicClient;
|
|
1832
|
-
/** Operator wallet — pays gas, receives the operator fee. */
|
|
1833
|
-
operatorWallet: OperatorWalletLike;
|
|
1834
1455
|
auth: {
|
|
1835
1456
|
jwtSecret: string;
|
|
1836
1457
|
/** SIWE-style login-message domain, e.g. `"app.example.com"`. */
|
|
@@ -1839,18 +1460,23 @@ interface IssuerServiceConfig {
|
|
|
1839
1460
|
jwtExpiresIn?: string;
|
|
1840
1461
|
};
|
|
1841
1462
|
/**
|
|
1842
|
-
*
|
|
1843
|
-
*
|
|
1844
|
-
*
|
|
1463
|
+
* Off-chain point ledger — the source of truth for user balances and
|
|
1464
|
+
* in-flight minting locks. Every issuer provides their own database-backed
|
|
1465
|
+
* implementation (Postgres, Redis, etc.) that implements `IPointLedger`.
|
|
1466
|
+
* The SDK does not ship a production ledger; each issuer's data model and
|
|
1467
|
+
* infrastructure are different.
|
|
1468
|
+
*/
|
|
1469
|
+
ledger: IPointLedger;
|
|
1470
|
+
/**
|
|
1471
|
+
* Policy engine — optional, defaults to `DefaultPolicyEngine` which checks
|
|
1472
|
+
* off-chain balance. Extend or replace to add KYC, volume caps, etc.
|
|
1845
1473
|
*/
|
|
1846
|
-
signer: IIssuerSigner;
|
|
1847
|
-
ledger?: IPointLedger;
|
|
1848
1474
|
policy?: IPolicyEngine;
|
|
1475
|
+
/** Session store — optional, defaults to `MemorySessionStore` (dev/test only). */
|
|
1849
1476
|
sessionStore?: ISessionStore;
|
|
1850
1477
|
/**
|
|
1851
1478
|
* Fee management config. If omitted the `handleGasFee` endpoint will
|
|
1852
|
-
* throw "not configured" at request time.
|
|
1853
|
-
* to opt in — `provider` is inherited from the outer config.
|
|
1479
|
+
* throw "not configured" at request time.
|
|
1854
1480
|
*/
|
|
1855
1481
|
fee?: Omit<FeeManagerConfig, "provider">;
|
|
1856
1482
|
/**
|
|
@@ -1858,6 +1484,16 @@ interface IssuerServiceConfig {
|
|
|
1858
1484
|
* throws "not configured" at request time.
|
|
1859
1485
|
*/
|
|
1860
1486
|
poolsProvider?: PoolsProvider;
|
|
1487
|
+
/**
|
|
1488
|
+
* Enables `handleClaim`. The factory combines these with the shared
|
|
1489
|
+
* `policy` + `relayService` instances already wired by the factory.
|
|
1490
|
+
* Omit to disable the `/claim` endpoint.
|
|
1491
|
+
*/
|
|
1492
|
+
claim?: {
|
|
1493
|
+
issuerSignerWallet: WalletClient;
|
|
1494
|
+
batchExecutorAddress: Address;
|
|
1495
|
+
lockDurationMs?: number;
|
|
1496
|
+
};
|
|
1861
1497
|
indexer?: {
|
|
1862
1498
|
fromBlock?: bigint;
|
|
1863
1499
|
cursorStore?: IIndexerCursorStore;
|
|
@@ -1870,32 +1506,18 @@ interface IssuerServiceConfig {
|
|
|
1870
1506
|
*/
|
|
1871
1507
|
autoStart?: boolean;
|
|
1872
1508
|
};
|
|
1873
|
-
relay?: {
|
|
1874
|
-
simulateBeforeSubmit?: boolean;
|
|
1875
|
-
confirmationTimeoutMs?: number;
|
|
1876
|
-
};
|
|
1877
|
-
gateway?: {
|
|
1878
|
-
/** Extra lock TTL buffer beyond consent deadline. Default 60_000 ms. */
|
|
1879
|
-
defaultLockBufferMs?: number;
|
|
1880
|
-
};
|
|
1881
1509
|
}
|
|
1882
1510
|
interface IssuerService {
|
|
1883
1511
|
authService: AuthService;
|
|
1884
1512
|
sessionStore: ISessionStore;
|
|
1885
1513
|
ledger: IPointLedger;
|
|
1886
1514
|
policy: IPolicyEngine;
|
|
1887
|
-
signer: IIssuerSigner;
|
|
1888
1515
|
relayService: RelayService;
|
|
1889
1516
|
feeManager: FeeManager | undefined;
|
|
1890
|
-
|
|
1891
|
-
/**
|
|
1892
|
-
* All indexers keyed by PointToken address. For multi-token issuers there
|
|
1893
|
-
* is one per configured token. Single-token issuers will find one entry.
|
|
1894
|
-
*/
|
|
1517
|
+
/** All indexers keyed by PointToken address. */
|
|
1895
1518
|
indexers: Map<Address, PointIndexer>;
|
|
1896
1519
|
/**
|
|
1897
|
-
* First indexer. Kept for backward compat with 0.1.x callers
|
|
1898
|
-
* expected `service.indexer` to be a single instance.
|
|
1520
|
+
* First indexer. Kept for backward compat with 0.1.x callers.
|
|
1899
1521
|
* @deprecated use `indexers.get(tokenAddress)` for multi-token.
|
|
1900
1522
|
*/
|
|
1901
1523
|
indexer: PointIndexer;
|
|
@@ -1903,23 +1525,19 @@ interface IssuerService {
|
|
|
1903
1525
|
}
|
|
1904
1526
|
/**
|
|
1905
1527
|
* Wire a fully-functional issuer service from a single config object.
|
|
1906
|
-
* Returns every constructed collaborator so the caller can also use the
|
|
1907
|
-
* indexer or relay service directly outside the HTTP layer.
|
|
1908
1528
|
*
|
|
1909
1529
|
* Defaults:
|
|
1910
|
-
* - `
|
|
1911
|
-
* - `sessionStore` → `MemorySessionStore`
|
|
1530
|
+
* - `sessionStore` → `MemorySessionStore` (dev/test only — replace in prod)
|
|
1912
1531
|
* - `policy` → `DefaultPolicyEngine({ ledger })`
|
|
1913
1532
|
* - `feeManager` → undefined (handleGasFee throws until configured)
|
|
1914
1533
|
* - `poolsProvider` → undefined (handlePools throws until configured)
|
|
1915
1534
|
* - `indexer.autoStart` → false
|
|
1916
1535
|
*
|
|
1917
|
-
* Throws synchronously if any required field
|
|
1918
|
-
* `operatorWallet`, `auth.jwtSecret`, at least one point token) is missing.
|
|
1536
|
+
* Throws synchronously if any required field is missing.
|
|
1919
1537
|
*/
|
|
1920
1538
|
declare function createIssuerService(config: IssuerServiceConfig): IssuerService;
|
|
1921
1539
|
|
|
1922
1540
|
/** SDK package version — bumped on every release */
|
|
1923
1541
|
declare const PAFI_ISSUER_SDK_VERSION = "0.1.0";
|
|
1924
1542
|
|
|
1925
|
-
export { type ApiBuildConsentTypedDataRequest, type ApiBuildConsentTypedDataResponse, type ApiClaimAndSwapRequest, type ApiClaimAndSwapResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, 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
|
|
1543
|
+
export { type ApiBuildConsentTypedDataRequest, type ApiBuildConsentTypedDataResponse, type ApiClaimAndSwapRequest, type ApiClaimAndSwapResponse, type ApiClaimRequest, type ApiClaimResponse, type ApiConfigResponse, type ApiGasFeeResponse, type ApiLoginRequest, type ApiLoginResponse, type ApiNonceResponse, type ApiPoolsRequest, type ApiPoolsResponse, 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, 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 RetryConfig, type Session, type SubgraphNativeUsdtQuoterConfig, type SubgraphPoolsProviderConfig, TopUpRedemptionError, TopUpRedemptionHandler, type TopUpRedemptionHandlerConfig, type TopUpRedemptionRequest, type TopUpRedemptionResponse, authenticateRequest, createIssuerService, createSubgraphNativeUsdtQuoter, createSubgraphPoolsProvider };
|