@pafi-dev/issuer 0.4.0 → 0.5.0
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 +182 -83
- package/dist/index.cjs +6 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -6
- package/dist/index.d.ts +11 -6
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/package.json +11 -11
package/README.md
CHANGED
|
@@ -1,67 +1,73 @@
|
|
|
1
1
|
# @pafi-dev/issuer
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
flow: SIWE authentication, point ledger, policy engine, EIP-712 issuer
|
|
6
|
-
signing, relay submission, and mint/burn event indexing.
|
|
3
|
+
[](https://www.npmjs.com/package/@pafi-dev/issuer)
|
|
4
|
+
[](https://opensource.org/licenses/Apache-2.0)
|
|
7
5
|
|
|
8
|
-
|
|
6
|
+
Issuer backend SDK for the PAFI point token system. Wraps `@pafi-dev/core` with everything
|
|
7
|
+
a partner needs to run the off-chain side of the cashout flow: SIWE authentication, point
|
|
8
|
+
ledger, policy engine, EIP-712 issuer signing, relay submission, and mint/burn event indexing.
|
|
9
9
|
|
|
10
|
-
> This package
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
> **Server-only.** This package pulls in `jose` and `node:crypto`. Do not bundle into a browser app.
|
|
11
|
+
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
## Requirements
|
|
15
|
+
|
|
16
|
+
- Node.js >= 18
|
|
17
|
+
- TypeScript >= 5.0
|
|
18
|
+
- `viem` ^2.0.0 and `@pafi-dev/core` ^0.4.0 (peer dependencies)
|
|
13
19
|
|
|
14
20
|
---
|
|
15
21
|
|
|
16
22
|
## Installation
|
|
17
23
|
|
|
18
24
|
```bash
|
|
25
|
+
npm install @pafi-dev/issuer @pafi-dev/core viem
|
|
26
|
+
# or
|
|
19
27
|
pnpm add @pafi-dev/issuer @pafi-dev/core viem
|
|
20
28
|
```
|
|
21
29
|
|
|
22
30
|
---
|
|
23
31
|
|
|
24
|
-
##
|
|
32
|
+
## Modules
|
|
25
33
|
|
|
26
|
-
| Module | What it
|
|
27
|
-
|
|
28
|
-
| `relay/` | `RelayService
|
|
29
|
-
| `
|
|
30
|
-
| `auth/` | `AuthService` (SIWE verify + JWT issue) + `authenticateRequest` middleware |
|
|
34
|
+
| Module | What it provides |
|
|
35
|
+
|---|---|
|
|
36
|
+
| `relay/` | `RelayService` — build unsigned UserOps for mint + burn |
|
|
37
|
+
| `auth/` | `AuthService` — SIWE verification + JWT issuance; `authenticateRequest` middleware |
|
|
31
38
|
| `ledger/` | `IPointLedger` interface — implement against your own database |
|
|
32
|
-
| `policy/` | `DefaultPolicyEngine`
|
|
33
|
-
| `
|
|
39
|
+
| `policy/` | `IPolicyEngine`, `DefaultPolicyEngine` — off-chain balance gate |
|
|
40
|
+
| `indexer/` | `PointIndexer` (mint events) + `BurnIndexer` (burn events) |
|
|
34
41
|
| `balance/` | `BalanceAggregator` — merge off-chain ledger + on-chain `balanceOf` |
|
|
35
|
-
| `api/` | `IssuerApiHandlers
|
|
42
|
+
| `api/` | `IssuerApiHandlers` — framework-agnostic HTTP handlers |
|
|
43
|
+
| `pafi-backend/` | `PafiBackendClient` — HTTP client for PAFI paymaster backend |
|
|
36
44
|
|
|
37
45
|
---
|
|
38
46
|
|
|
39
47
|
## What you must bring
|
|
40
48
|
|
|
41
|
-
The SDK deliberately does not ship production implementations for
|
|
42
|
-
three concerns — every issuer's infrastructure is different:
|
|
49
|
+
The SDK deliberately does not ship production implementations for:
|
|
43
50
|
|
|
44
51
|
| What | Why you own it |
|
|
45
|
-
|
|
46
|
-
| **`IPointLedger`** | Your database, your schema, your locking strategy |
|
|
47
|
-
| **`ISessionStore`** | Must be shared across pods — Redis
|
|
52
|
+
|---|---|
|
|
53
|
+
| **`IPointLedger`** | Your database, your schema, your row-level locking strategy |
|
|
54
|
+
| **`ISessionStore`** | Must be shared across pods — use Redis or Postgres |
|
|
48
55
|
| **Signing wallet** | Private key must never touch server memory — use KMS |
|
|
49
56
|
|
|
50
|
-
See [`examples/adapters/`](./examples/adapters/) for reference implementations
|
|
51
|
-
of all three (Postgres ledger, Redis session store, AWS KMS wallet).
|
|
52
|
-
|
|
53
57
|
---
|
|
54
58
|
|
|
55
59
|
## Quick start
|
|
56
60
|
|
|
57
61
|
```ts
|
|
58
62
|
import { createIssuerService } from "@pafi-dev/issuer";
|
|
63
|
+
import { getContractAddresses } from "@pafi-dev/core";
|
|
59
64
|
import { createPublicClient, createWalletClient, http } from "viem";
|
|
60
65
|
import { base } from "viem/chains";
|
|
61
|
-
|
|
62
|
-
// --- Production: replace with KMS-backed wallet (see examples/adapters/kms-signer.ts)
|
|
63
|
-
// --- Dev only: raw private key
|
|
64
66
|
import { privateKeyToAccount } from "viem/accounts";
|
|
67
|
+
|
|
68
|
+
const addrs = getContractAddresses(8453);
|
|
69
|
+
|
|
70
|
+
// Production: replace with a KMS-backed WalletClient (see "Production signing" below)
|
|
65
71
|
const issuerSignerWallet = createWalletClient({
|
|
66
72
|
account: privateKeyToAccount(process.env.MINTER_PRIVATE_KEY as `0x${string}`),
|
|
67
73
|
chain: base,
|
|
@@ -70,27 +76,27 @@ const issuerSignerWallet = createWalletClient({
|
|
|
70
76
|
|
|
71
77
|
const service = createIssuerService({
|
|
72
78
|
chainId: 8453,
|
|
73
|
-
pointTokenAddresses: [
|
|
79
|
+
pointTokenAddresses: [addrs.pointToken],
|
|
74
80
|
contracts: {
|
|
75
|
-
relay:
|
|
76
|
-
issuerRegistry:
|
|
77
|
-
usdt:
|
|
78
|
-
batchExecutor:
|
|
81
|
+
relay: "0x92327F5c9383796Dd46D43E0995cc938038A98c4",
|
|
82
|
+
issuerRegistry: addrs.issuerRegistry,
|
|
83
|
+
usdt: addrs.usdt,
|
|
84
|
+
batchExecutor: addrs.batchExecutor,
|
|
79
85
|
},
|
|
80
86
|
provider: createPublicClient({ chain: base, transport: http(process.env.RPC_URL) }),
|
|
81
87
|
auth: {
|
|
82
88
|
jwtSecret: process.env.JWT_SECRET!,
|
|
83
89
|
domain: "app.example.com",
|
|
84
90
|
},
|
|
85
|
-
ledger: new YourPostgresLedger(),
|
|
91
|
+
ledger: new YourPostgresLedger(), // implements IPointLedger
|
|
86
92
|
sessionStore: new YourRedisSessionStore(), // implements ISessionStore
|
|
87
93
|
claim: {
|
|
88
94
|
issuerSignerWallet,
|
|
89
|
-
batchExecutorAddress:
|
|
95
|
+
batchExecutorAddress: addrs.batchExecutor,
|
|
90
96
|
},
|
|
91
97
|
});
|
|
92
98
|
|
|
93
|
-
// Mount
|
|
99
|
+
// Mount into your framework (Express, Fastify, NestJS, Hono...)
|
|
94
100
|
app.get("/auth/nonce", () => service.handlers.handleGetNonce());
|
|
95
101
|
app.post("/auth/login", (req) => service.handlers.handleLogin(req.body));
|
|
96
102
|
app.get("/user", (req) => service.handlers.handleUser(req.user, req.query));
|
|
@@ -101,124 +107,217 @@ app.post("/claim", (req) => service.handlers.handleClaim(req.user, req.body
|
|
|
101
107
|
|
|
102
108
|
## Implementing IPointLedger
|
|
103
109
|
|
|
110
|
+
Every issuer provides their own database-backed implementation:
|
|
111
|
+
|
|
104
112
|
```ts
|
|
105
|
-
import type { IPointLedger } from "@pafi-dev/issuer";
|
|
113
|
+
import type { IPointLedger, LockedMintRequest, MintingStatus } from "@pafi-dev/issuer";
|
|
106
114
|
import type { Address, Hex } from "viem";
|
|
107
115
|
|
|
108
116
|
export class PostgresPointLedger implements IPointLedger {
|
|
109
117
|
async getBalance(user: Address, tokenAddress?: Address): Promise<bigint> { ... }
|
|
118
|
+
|
|
119
|
+
// Must use a row-level lock (SELECT ... FOR UPDATE) to prevent
|
|
120
|
+
// concurrent pods from reading the same available balance and double-spending.
|
|
110
121
|
async lockForMinting(user: Address, amount: bigint, durationMs: number, tokenAddress?: Address): Promise<string> { ... }
|
|
122
|
+
|
|
111
123
|
async releaseLock(lockId: string): Promise<void> { ... }
|
|
112
124
|
async deductBalance(user: Address, amount: bigint, txHash: Hex, tokenAddress?: Address): Promise<void> { ... }
|
|
113
125
|
async creditBalance(user: Address, amount: bigint, reason: string, tokenAddress?: Address): Promise<void> { ... }
|
|
114
126
|
async getLockedRequests(user: Address, tokenAddress?: Address): Promise<LockedMintRequest[]> { ... }
|
|
115
127
|
async updateMintStatus(lockId: string, status: MintingStatus, txHash?: Hex): Promise<void> { ... }
|
|
116
|
-
|
|
128
|
+
|
|
129
|
+
// Burn flow: reserve → resolve when burn tx confirmed
|
|
117
130
|
async reservePendingCredit(user: Address, amount: bigint, durationMs: number, tokenAddress?: Address): Promise<string> { ... }
|
|
118
131
|
async resolveCreditByBurnTx(lockId: string, txHash: Hex): Promise<void> { ... }
|
|
119
132
|
}
|
|
120
133
|
```
|
|
121
134
|
|
|
122
|
-
Critical: `lockForMinting` must use a **row-level lock** (e.g. `SELECT ... FOR UPDATE`)
|
|
123
|
-
so concurrent requests from multiple pods cannot read the same available balance and
|
|
124
|
-
double-spend.
|
|
125
|
-
|
|
126
|
-
See `examples/adapters/postgres-ledger.ts` for a full Prisma implementation.
|
|
127
|
-
|
|
128
135
|
---
|
|
129
136
|
|
|
130
137
|
## Production signing — KMS
|
|
131
138
|
|
|
132
|
-
|
|
133
|
-
The SDK accepts any viem `WalletClient` — wire it to AWS KMS
|
|
134
|
-
a custom account:
|
|
139
|
+
In production the `issuerSignerWallet` must be backed by a hardware key.
|
|
140
|
+
The SDK accepts any viem `WalletClient` — wire it to AWS KMS via a custom account:
|
|
135
141
|
|
|
136
142
|
```ts
|
|
137
|
-
import { createKmsWalletClient } from "./adapters/kms-signer";
|
|
138
143
|
import { KMSClient } from "@aws-sdk/client-kms";
|
|
144
|
+
import { createWalletClient, http } from "viem";
|
|
145
|
+
import { base } from "viem/chains";
|
|
139
146
|
|
|
140
|
-
|
|
147
|
+
// Custom viem account that delegates signTypedData to KMS.
|
|
148
|
+
// Full DER→(r,s) conversion + v-byte recovery omitted for brevity.
|
|
149
|
+
const kmsAccount = toAccount({
|
|
150
|
+
address: process.env.KMS_MINTER_ADDRESS as `0x${string}`,
|
|
151
|
+
async signTypedData(typedData) {
|
|
152
|
+
const digest = hashTypedData(typedData);
|
|
153
|
+
const { Signature } = await kms.send(new SignCommand({
|
|
154
|
+
KeyId: process.env.KMS_MINTER_KEY_ID!,
|
|
155
|
+
Message: digest,
|
|
156
|
+
MessageType: "DIGEST",
|
|
157
|
+
SigningAlgorithm: "ECDSA_SHA_256",
|
|
158
|
+
}));
|
|
159
|
+
return derToViem(Signature!); // convert DER → 65-byte viem hex signature
|
|
160
|
+
},
|
|
161
|
+
});
|
|
141
162
|
|
|
142
|
-
const issuerSignerWallet =
|
|
143
|
-
|
|
144
|
-
keyId: process.env.KMS_MINTER_KEY_ID!,
|
|
145
|
-
address: process.env.KMS_MINTER_ADDRESS! as `0x${string}`,
|
|
163
|
+
const issuerSignerWallet = createWalletClient({
|
|
164
|
+
account: kmsAccount,
|
|
146
165
|
chain: base,
|
|
166
|
+
transport: http(process.env.RPC_URL),
|
|
147
167
|
});
|
|
148
168
|
```
|
|
149
169
|
|
|
150
|
-
See `examples/adapters/kms-signer.ts` for the full implementation including
|
|
151
|
-
DER→(r,s) conversion and v-byte recovery.
|
|
152
|
-
|
|
153
170
|
---
|
|
154
171
|
|
|
155
|
-
##
|
|
172
|
+
## Event indexers
|
|
173
|
+
|
|
174
|
+
Indexers sync on-chain mint/burn events back to the off-chain ledger.
|
|
156
175
|
|
|
157
176
|
```ts
|
|
158
177
|
import { PointIndexer, BurnIndexer } from "@pafi-dev/issuer";
|
|
178
|
+
import { getContractAddresses } from "@pafi-dev/core";
|
|
159
179
|
|
|
160
|
-
|
|
161
|
-
|
|
180
|
+
const addrs = getContractAddresses(8453);
|
|
181
|
+
|
|
182
|
+
// Mint indexer: Transfer(0x0 → user) → deducts off-chain locked balance
|
|
183
|
+
const mintIndexer = new PointIndexer({
|
|
162
184
|
provider: publicClient,
|
|
163
|
-
pointTokenAddress:
|
|
185
|
+
pointTokenAddress: addrs.pointToken,
|
|
164
186
|
ledger,
|
|
165
|
-
cursorStore,
|
|
187
|
+
cursorStore, // persists last-processed block; use Postgres or Redis
|
|
166
188
|
fromBlock: 28_000_000n,
|
|
167
189
|
confirmations: 2,
|
|
168
190
|
pollIntervalMs: 3_000,
|
|
169
191
|
});
|
|
170
|
-
pointIndexer.start();
|
|
171
192
|
|
|
172
|
-
//
|
|
193
|
+
// Burn indexer: Transfer(user → 0x0) → resolves pending off-chain credit
|
|
173
194
|
const burnIndexer = new BurnIndexer({
|
|
174
195
|
provider: publicClient,
|
|
175
|
-
pointTokenAddress:
|
|
196
|
+
pointTokenAddress: addrs.pointToken,
|
|
176
197
|
ledger,
|
|
177
198
|
cursorStore,
|
|
178
199
|
matchLockId: async (evt) => {
|
|
179
|
-
// Return the lockId from
|
|
180
|
-
//
|
|
181
|
-
return
|
|
200
|
+
// Return the lockId from reservePendingCredit() that matches this burn.
|
|
201
|
+
// Typically a DB lookup by (from, amount, status=PENDING).
|
|
202
|
+
return db.findPendingCreditLockId(evt.from, evt.amount);
|
|
182
203
|
},
|
|
183
204
|
});
|
|
205
|
+
|
|
206
|
+
mintIndexer.start();
|
|
184
207
|
burnIndexer.start();
|
|
185
208
|
```
|
|
186
209
|
|
|
187
|
-
Indexers must be
|
|
188
|
-
Use a Kubernetes Deployment with `replicas: 1
|
|
210
|
+
> **Indexers must be singletons.** Run exactly one instance per token per deployment.
|
|
211
|
+
> Use a Kubernetes `Deployment` with `replicas: 1`.
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## PafiBackendClient
|
|
216
|
+
|
|
217
|
+
HTTP client for requesting paymaster sponsorship from the PAFI backend:
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
import { PafiBackendClient } from "@pafi-dev/issuer";
|
|
221
|
+
|
|
222
|
+
const pafiClient = new PafiBackendClient({
|
|
223
|
+
url: "https://api-dev.pacificfinance.org/api/sponsor",
|
|
224
|
+
issuerId: "gg56",
|
|
225
|
+
apiKey: process.env.PAFI_API_KEY!,
|
|
226
|
+
retry: { maxAttempts: 3, maxRetryAfterMs: 5_000 },
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
const sponsorship = await pafiClient.requestSponsorship({
|
|
230
|
+
chainId: 8453,
|
|
231
|
+
scenario: "mint",
|
|
232
|
+
userOp: {
|
|
233
|
+
sender: userAddress,
|
|
234
|
+
callData: userOp.callData,
|
|
235
|
+
// ...gas fields
|
|
236
|
+
},
|
|
237
|
+
target: {
|
|
238
|
+
contractAddress: addrs.pointToken,
|
|
239
|
+
functionSelector: "0x...",
|
|
240
|
+
},
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
// sponsorship.paymaster
|
|
244
|
+
// sponsorship.paymasterData
|
|
245
|
+
// sponsorship.paymasterVerificationGasLimit
|
|
246
|
+
// sponsorship.paymasterPostOpGasLimit
|
|
247
|
+
// sponsorship.expiresAt
|
|
248
|
+
```
|
|
189
249
|
|
|
190
250
|
---
|
|
191
251
|
|
|
192
|
-
## Error
|
|
252
|
+
## Error handling
|
|
253
|
+
|
|
254
|
+
### AuthError
|
|
255
|
+
|
|
256
|
+
Thrown by `AuthService` and `authenticateRequest` middleware:
|
|
257
|
+
|
|
258
|
+
```ts
|
|
259
|
+
import { AuthError, type AuthErrorCode } from "@pafi-dev/issuer";
|
|
260
|
+
|
|
261
|
+
// AuthErrorCode:
|
|
262
|
+
// "INVALID_MESSAGE" | "INVALID_SIGNATURE" | "NONCE_MISMATCH"
|
|
263
|
+
// "NONCE_EXPIRED" | "TOKEN_EXPIRED" | "TOKEN_INVALID"
|
|
264
|
+
// "SESSION_NOT_FOUND" | "DOMAIN_MISMATCH" | "CHAIN_MISMATCH"
|
|
265
|
+
|
|
266
|
+
try {
|
|
267
|
+
const user = await authService.login(message, signature);
|
|
268
|
+
} catch (err) {
|
|
269
|
+
if (err instanceof AuthError) {
|
|
270
|
+
console.log(err.code); // AuthErrorCode
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
### PafiBackendError
|
|
276
|
+
|
|
277
|
+
Thrown by `PafiBackendClient`:
|
|
193
278
|
|
|
194
279
|
```ts
|
|
195
280
|
import { PafiBackendError, type PafiBackendErrorCode } from "@pafi-dev/issuer";
|
|
196
281
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
282
|
+
// PafiBackendErrorCode:
|
|
283
|
+
// "RATE_LIMIT_EXCEEDED" | "RATE_LIMIT_EXCEEDED_DAILY" | "RATE_LIMIT_EXCEEDED_PER_USER"
|
|
284
|
+
// "RATE_LIMITER_UNAVAILABLE"
|
|
285
|
+
// "INTENT_REJECTED" | "MINT_CAP_EXCEEDED" | "ISSUER_INACTIVE"
|
|
286
|
+
// "ISSUER_UNAUTHORIZED" | "USER_UNAUTHORIZED"
|
|
287
|
+
// "PAYMASTER_UNAVAILABLE" | "TARGET_NOT_ALLOWLISTED"
|
|
288
|
+
// "BAD_REQUEST" | "INTERNAL_ERROR" | "TIMEOUT" | "NETWORK_ERROR"
|
|
289
|
+
|
|
290
|
+
try {
|
|
291
|
+
await pafiClient.requestSponsorship(request);
|
|
292
|
+
} catch (err) {
|
|
293
|
+
if (err instanceof PafiBackendError) {
|
|
294
|
+
if (err.code === "RATE_LIMIT_EXCEEDED") {
|
|
295
|
+
// err.retryAfter — seconds to wait before retrying
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
203
299
|
```
|
|
204
300
|
|
|
205
301
|
---
|
|
206
302
|
|
|
207
303
|
## Changelog
|
|
208
304
|
|
|
305
|
+
### 0.4.0
|
|
306
|
+
- `PafiBackendClient` added — HTTP client for PAFI paymaster backend with retry logic and bigint serialization
|
|
307
|
+
- `SponsorAuth` support — issuer signs EIP-712 authorization for FE to request paymaster sponsorship
|
|
308
|
+
- `PAYMASTER_UNAVAILABLE`, `TARGET_NOT_ALLOWLISTED` added to `PafiBackendErrorCode`
|
|
309
|
+
|
|
209
310
|
### 0.3.0-beta.10
|
|
210
|
-
- `MemoryPointLedger` removed from public exports — each issuer
|
|
211
|
-
- `PrivateKeySigner` / `IIssuerSigner` removed — SDK accepts viem `WalletClient` directly
|
|
212
|
-
- `ledger` is now a required field in `IssuerServiceConfig`
|
|
213
|
-
- `handleClaim` added to `IssuerApiHandlers`
|
|
311
|
+
- `MemoryPointLedger` removed from public exports — each issuer must implement `IPointLedger`
|
|
312
|
+
- `PrivateKeySigner` / `IIssuerSigner` removed — SDK accepts viem `WalletClient` directly
|
|
313
|
+
- `ledger` is now a required field in `IssuerServiceConfig`
|
|
314
|
+
- `handleClaim` added to `IssuerApiHandlers`
|
|
214
315
|
|
|
215
316
|
### 0.3.0-beta.9
|
|
216
|
-
- `
|
|
217
|
-
- `PTRedeemHandler` enforces on-chain balance check before signing BurnRequest
|
|
317
|
+
- `PTRedeemHandler` enforces on-chain balance check before signing `BurnRequest`
|
|
218
318
|
|
|
219
319
|
### 0.3.0-beta.8
|
|
220
320
|
- `BalanceAggregator`, `BurnIndexer`, `PTRedeemHandler`, `TopUpRedemptionHandler`
|
|
221
|
-
- `BurnIndexer.matchLockId` is now required (throws if not provided)
|
|
222
321
|
|
|
223
322
|
### 0.3.0-alpha.0
|
|
224
323
|
- Initial `RelayService`, `PointIndexer`, `AuthService`, `IssuerApiHandlers`
|
package/dist/index.cjs
CHANGED
|
@@ -2062,20 +2062,20 @@ function createIssuerService(config) {
|
|
|
2062
2062
|
}
|
|
2063
2063
|
}
|
|
2064
2064
|
return {
|
|
2065
|
-
authService,
|
|
2066
|
-
sessionStore,
|
|
2065
|
+
auth: authService,
|
|
2066
|
+
session: sessionStore,
|
|
2067
2067
|
ledger,
|
|
2068
2068
|
policy,
|
|
2069
|
-
relayService,
|
|
2070
|
-
feeManager,
|
|
2069
|
+
relay: relayService,
|
|
2070
|
+
fee: feeManager,
|
|
2071
2071
|
indexers,
|
|
2072
2072
|
indexer: firstIndexer,
|
|
2073
|
-
handlers
|
|
2073
|
+
api: handlers
|
|
2074
2074
|
};
|
|
2075
2075
|
}
|
|
2076
2076
|
|
|
2077
2077
|
// src/index.ts
|
|
2078
|
-
var PAFI_ISSUER_SDK_VERSION = "0.
|
|
2078
|
+
var PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
2079
2079
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2080
2080
|
0 && (module.exports = {
|
|
2081
2081
|
AuthError,
|