@pafi-dev/issuer 0.12.7 → 0.15.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 +172 -95
- package/dist/index.cjs +107 -148
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +144 -127
- package/dist/index.d.ts +144 -127
- package/dist/index.js +93 -137
- package/dist/index.js.map +1 -1
- package/package.json +13 -2
package/README.md
CHANGED
|
@@ -4,25 +4,30 @@
|
|
|
4
4
|
[](https://opensource.org/licenses/Apache-2.0)
|
|
5
5
|
|
|
6
6
|
Backend SDK for PAFI issuer servers — claim, redeem, perp deposit,
|
|
7
|
-
mobile prepare/submit, EIP-7702 delegation, status polling,
|
|
8
|
-
`IssuerApiAdapter` that thins issuer
|
|
9
|
-
endpoint.
|
|
7
|
+
mobile prepare/submit, EIP-7702 delegation, status polling, redemption
|
|
8
|
+
restriction enforcement, and the `IssuerApiAdapter` that thins issuer
|
|
9
|
+
controllers to one line per endpoint.
|
|
10
10
|
|
|
11
11
|
**Server-only.** Pulls in signer wallets, HTTP clients, ledger
|
|
12
12
|
interfaces. Don't bundle into a browser app — use
|
|
13
|
-
`@pafi-dev/trading` (FE swap/quote) or `@pafi-dev/core` (primitives)
|
|
14
|
-
instead.
|
|
13
|
+
`@pafi-dev/trading` (FE swap/quote) or `@pafi-dev/core` (primitives).
|
|
15
14
|
|
|
16
15
|
---
|
|
17
16
|
|
|
17
|
+
## v0.15.0 — Uniswap V3 migration (breaking)
|
|
18
|
+
|
|
19
|
+
- `createSubgraphPoolsProvider` now returns the V3 `PoolKey` shape (`{ token0, token1, fee }`) instead of the V4 shape (`{ currency0, currency1, fee, tickSpacing, hooks }`). Pulls through from `@pafi-dev/core`.
|
|
20
|
+
- New `onError?: (err: Error) => void` option — forward recoverable errors (network, GraphQL, parse) to your observability stack. Throws inside the callback are swallowed so the provider stays total.
|
|
21
|
+
- `feeTier` is range-checked (uint24, < 1_000_000) before building the `PoolKey`; invalid values are skipped with a console.error + `onError` invocation.
|
|
22
|
+
- Subgraph endpoint default → `…/pafi-subgraph-v4` (PAFI V3-fork DEX + extensions); see `@pafi-dev/core` for the constant.
|
|
23
|
+
- Bumps peer-deps on `@pafi-dev/core` to `^0.13.0` (V3 types + ABIs).
|
|
24
|
+
|
|
18
25
|
## Requirements
|
|
19
26
|
|
|
20
|
-
- Node.js
|
|
21
|
-
- TypeScript
|
|
27
|
+
- Node.js ≥ 18
|
|
28
|
+
- TypeScript ≥ 5.0
|
|
22
29
|
- `viem` ^2.0.0 (peer)
|
|
23
|
-
- `@pafi-dev/core` (
|
|
24
|
-
|
|
25
|
-
---
|
|
30
|
+
- `@pafi-dev/core` ^0.13.0 (transitive — re-exported)
|
|
26
31
|
|
|
27
32
|
## Installation
|
|
28
33
|
|
|
@@ -38,11 +43,9 @@ pnpm add @pafi-dev/issuer-postgres typeorm pg
|
|
|
38
43
|
|
|
39
44
|
```
|
|
40
45
|
@pafi-dev/issuer
|
|
41
|
-
├── handlers —
|
|
42
|
-
│ PerpDepositHandler)
|
|
46
|
+
├── handlers — PTClaimHandler, PTRedeemHandler, PerpDepositHandler
|
|
43
47
|
├── api/IssuerApiAdapter
|
|
44
|
-
│ — single class, every endpoint is one line in
|
|
45
|
-
│ your controller
|
|
48
|
+
│ — single class, every endpoint is one line in controller
|
|
46
49
|
├── api/handleMobilePrepare/Submit
|
|
47
50
|
│ — mobile claim/redeem orchestrators
|
|
48
51
|
├── api/handleClaimStatus/handleRedeemStatus
|
|
@@ -55,20 +58,15 @@ pnpm add @pafi-dev/issuer-postgres typeorm pg
|
|
|
55
58
|
├── userop-store — IPendingUserOpStore + MemoryPendingUserOpStore
|
|
56
59
|
├── pafi-backend — sponsor-relayer client + relay/paymaster helpers
|
|
57
60
|
├── auth — ISessionStore, AuthService (SIWE), MemorySessionStore
|
|
58
|
-
├── relay — RelayService, FeeManager
|
|
61
|
+
├── relay — RelayService (wrapper-aware), FeeManager
|
|
59
62
|
├── pools — createSubgraphPoolsProvider, NativePtQuoter
|
|
60
63
|
├── policy — IPolicyEngine + DefaultPolicyEngine
|
|
61
|
-
├──
|
|
62
|
-
├──
|
|
63
|
-
├──
|
|
64
|
+
├── indexer — PointIndexer (wrapper + direct mode), BurnIndexer
|
|
65
|
+
├── issuer-state — IssuerStateValidator (7-field struct + oracle.tokenCaps)
|
|
66
|
+
├── redemption — RedemptionService (per-issuer policy enforcement)
|
|
64
67
|
└── errors — PafiSdkError base class for typed errors
|
|
65
68
|
```
|
|
66
69
|
|
|
67
|
-
> **Removed in 0.6.0** (2026-04-27): `SwapHandler`, `quotePointTokenToUsdt`,
|
|
68
|
-
> and `IssuerApiAdapter.swap()/quote()` — moved to `@pafi-dev/trading`.
|
|
69
|
-
> FE PAFI calls trading directly. `IssuerApiHandlers.handleClaim/handleRedeem`
|
|
70
|
-
> legacy methods + `TopUpRedemptionHandler` (Variant B) also dropped.
|
|
71
|
-
|
|
72
70
|
---
|
|
73
71
|
|
|
74
72
|
## Architecture
|
|
@@ -80,23 +78,63 @@ Auth guard ← issuer-specific (SIWE / Privy / NextAuth)
|
|
|
80
78
|
↓
|
|
81
79
|
Controller ← thin: routing + DTO + auth context
|
|
82
80
|
↓
|
|
83
|
-
IssuerApiAdapter ←
|
|
81
|
+
IssuerApiAdapter ← orchestrates flows
|
|
84
82
|
↓
|
|
85
|
-
PTClaimHandler ← signs
|
|
83
|
+
PTClaimHandler ← signs MintForRequest, locks balance, builds UserOp
|
|
84
|
+
(routes to wrapper.mintWithFee when wrapper configured)
|
|
86
85
|
PTRedeemHandler ← signs BurnRequest, reserves credit, builds UserOp
|
|
87
86
|
PerpDepositHandler ← Orderly Vault via PAFI Relay
|
|
88
87
|
↓
|
|
89
|
-
|
|
90
|
-
RelayService ← UserOp builders
|
|
88
|
+
IPointLedger ← your DB impl (Postgres recommended)
|
|
89
|
+
RelayService ← UserOp builders (auto-branches direct vs wrapper)
|
|
91
90
|
PafiBackendClient ← sponsor-relayer proxy
|
|
92
91
|
```
|
|
93
92
|
|
|
94
93
|
---
|
|
95
94
|
|
|
95
|
+
## Wrapper-mediated mint flow
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
[FE / mobile] → POST /claim/prepare
|
|
99
|
+
↓
|
|
100
|
+
[gg56] IssuerApiAdapter.claimPrepare()
|
|
101
|
+
↓
|
|
102
|
+
[gg56] PTClaimHandler:
|
|
103
|
+
1. Lock off-chain balance (gross amount)
|
|
104
|
+
2. Pre-validate via IssuerStateValidator (oracle cap check)
|
|
105
|
+
3. Sign MintForRequest EIP-712 with receiver = wrapper
|
|
106
|
+
4. Build UserOp callData:
|
|
107
|
+
BatchExecute([
|
|
108
|
+
{ mintFeeWrapper, mintWithFee(pt, user, gross, deadline, sig) },
|
|
109
|
+
{ pointToken, transfer(pafiFeeRecipient, operatorFeePT) }
|
|
110
|
+
])
|
|
111
|
+
↓
|
|
112
|
+
[gg56] PafiBackendClient.requestSponsorship() → sponsor-relayer
|
|
113
|
+
↓
|
|
114
|
+
[sponsor-relayer] decode calldata, recognize MINT_WITH_FEE (0x5284d08b),
|
|
115
|
+
validate intent, forward to Pimlico paymaster
|
|
116
|
+
↓
|
|
117
|
+
[gg56] returns { userOp, typedData, userOpHash, sponsored: true|false,
|
|
118
|
+
typedDataFallback, userOpHashFallback }
|
|
119
|
+
↓
|
|
120
|
+
[FE / mobile] sign typedData via signTypedData_v4
|
|
121
|
+
↓
|
|
122
|
+
[FE / mobile] POST /claim/submit { lockId, signature, variant }
|
|
123
|
+
↓
|
|
124
|
+
[gg56] forwards signed UserOp to Pimlico bundler → on-chain mint
|
|
125
|
+
↓
|
|
126
|
+
[chain] wrapper.mintWithFee → PointToken.mint(gross to wrapper) →
|
|
127
|
+
wrapper splits fee to recipients → transfers net to user
|
|
128
|
+
↓
|
|
129
|
+
[gg56] PointIndexer (wrapper mode) catches MintWithFee event →
|
|
130
|
+
deduct off-chain balance, lock → MINTED
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
96
135
|
## Quick start (NestJS)
|
|
97
136
|
|
|
98
|
-
Minimal reference at `examples/nestjs-issuer/` — full working backend
|
|
99
|
-
with all 11 endpoints, ~940 LoC total.
|
|
137
|
+
Minimal reference at `examples/nestjs-issuer/` — full working backend.
|
|
100
138
|
|
|
101
139
|
### 1. Wire `IssuerApiAdapter`
|
|
102
140
|
|
|
@@ -109,7 +147,6 @@ import {
|
|
|
109
147
|
PTRedeemHandler,
|
|
110
148
|
PerpDepositHandler,
|
|
111
149
|
MemoryPendingUserOpStore,
|
|
112
|
-
createSubgraphPoolsProvider,
|
|
113
150
|
type IssuerService,
|
|
114
151
|
} from "@pafi-dev/issuer";
|
|
115
152
|
import { PostgresPointLedger } from "@pafi-dev/issuer-postgres";
|
|
@@ -117,41 +154,48 @@ import { getContractAddresses } from "@pafi-dev/core";
|
|
|
117
154
|
|
|
118
155
|
export const issuerApiAdapterProvider: Provider = {
|
|
119
156
|
provide: ISSUER_API_ADAPTER,
|
|
120
|
-
useFactory: (issuerService, provider, walletClient, dataSource) => {
|
|
157
|
+
useFactory: (issuerService, provider, walletClient, dataSource, config) => {
|
|
121
158
|
const ledger = new PostgresPointLedger(dataSource);
|
|
122
159
|
const { issuerRegistry, batchExecutor } = getContractAddresses(8453);
|
|
160
|
+
const chainId = config.get<number>("CHAIN_ID");
|
|
161
|
+
const pointToken = config.get<`0x${string}`>("POINT_TOKEN_ADDRESS");
|
|
123
162
|
|
|
124
163
|
return new IssuerApiAdapter({
|
|
125
164
|
issuerService,
|
|
126
165
|
ledger,
|
|
127
166
|
provider,
|
|
128
167
|
issuerSignerWallet: walletClient,
|
|
129
|
-
pafiIssuerId:
|
|
168
|
+
pafiIssuerId: config.get("PAFI_ISSUER_ID"),
|
|
130
169
|
|
|
131
170
|
ptClaimHandler: new PTClaimHandler({
|
|
132
|
-
ledger,
|
|
171
|
+
ledger,
|
|
172
|
+
relayService: issuerService.relay,
|
|
173
|
+
provider,
|
|
133
174
|
issuerSignerWallet: walletClient,
|
|
134
|
-
pointTokenDomainName: "
|
|
175
|
+
pointTokenDomainName: config.get("POINT_TOKEN_DOMAIN_NAME"),
|
|
135
176
|
feeService: issuerService.fee,
|
|
136
177
|
issuerStateValidator: new IssuerStateValidator(provider, issuerRegistry),
|
|
178
|
+
// mintFeeWrapperAddress: optional override; SDK auto-resolves from chainId
|
|
137
179
|
}),
|
|
138
180
|
|
|
139
181
|
ptRedeemHandler: new PTRedeemHandler({
|
|
140
|
-
ledger,
|
|
141
|
-
|
|
182
|
+
ledger,
|
|
183
|
+
relayService: issuerService.relay,
|
|
184
|
+
provider,
|
|
185
|
+
pointTokenAddress: pointToken,
|
|
142
186
|
batchExecutorAddress: batchExecutor,
|
|
143
|
-
chainId
|
|
144
|
-
domain: { name: "
|
|
187
|
+
chainId,
|
|
188
|
+
domain: { name: config.get("POINT_TOKEN_DOMAIN_NAME"), verifyingContract: pointToken },
|
|
145
189
|
burnerSignerWallet: walletClient,
|
|
146
190
|
feeService: issuerService.fee,
|
|
147
191
|
}),
|
|
148
192
|
|
|
149
193
|
perpHandler: new PerpDepositHandler({
|
|
150
|
-
provider, feeService: issuerService.fee, pointTokenAddress:
|
|
194
|
+
provider, feeService: issuerService.fee, pointTokenAddress: pointToken,
|
|
151
195
|
}),
|
|
152
196
|
|
|
153
197
|
pendingUserOpStore: new MemoryPendingUserOpStore(),
|
|
154
|
-
pafiBackendClient, // optional —
|
|
198
|
+
pafiBackendClient, // optional — sponsor-relayer client for sponsored flows
|
|
155
199
|
});
|
|
156
200
|
},
|
|
157
201
|
inject: [...],
|
|
@@ -183,7 +227,6 @@ export class IssuerController {
|
|
|
183
227
|
aaNonce, mintRequestNonce,
|
|
184
228
|
}));
|
|
185
229
|
}
|
|
186
|
-
// ... other endpoints similarly thin
|
|
187
230
|
}
|
|
188
231
|
```
|
|
189
232
|
|
|
@@ -191,16 +234,12 @@ export class IssuerController {
|
|
|
191
234
|
|
|
192
235
|
```ts
|
|
193
236
|
import { createSdkErrorMapper, type SdkErrorBody } from "@pafi-dev/issuer";
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
notFound: (b: SdkErrorBody) => new NotFoundException(b),
|
|
201
|
-
forbidden: (b: SdkErrorBody) => new ForbiddenException(b),
|
|
202
|
-
unprocessable: (b: SdkErrorBody) => new UnprocessableEntityException(b),
|
|
203
|
-
serviceUnavailable: (b: SdkErrorBody) => new ServiceUnavailableException(b),
|
|
237
|
+
|
|
238
|
+
const sdkErrorMapper = createSdkErrorMapper({
|
|
239
|
+
notFound: (b) => new NotFoundException(b),
|
|
240
|
+
forbidden: (b) => new ForbiddenException(b),
|
|
241
|
+
unprocessable: (b) => new UnprocessableEntityException(b),
|
|
242
|
+
serviceUnavailable: (b) => new ServiceUnavailableException(b),
|
|
204
243
|
});
|
|
205
244
|
|
|
206
245
|
async function wrap<T>(fn: () => Promise<T>): Promise<T> {
|
|
@@ -209,91 +248,129 @@ async function wrap<T>(fn: () => Promise<T>): Promise<T> {
|
|
|
209
248
|
}
|
|
210
249
|
```
|
|
211
250
|
|
|
212
|
-
Every typed SDK error (`PafiSdkError` subclass) routes through this
|
|
213
|
-
funnel — `code`, `safeToRetry`, `details`, `httpStatus` come straight
|
|
214
|
-
off the error class. No magic strings, no per-error mapping.
|
|
215
|
-
|
|
216
251
|
---
|
|
217
252
|
|
|
218
253
|
## `IssuerApiAdapter` methods
|
|
219
254
|
|
|
220
|
-
| Method | HTTP route
|
|
221
|
-
| --- | --- |
|
|
222
|
-
| `pools(authedAddr, chainId, pointToken)` | `GET /pools` |
|
|
223
|
-
| `user(authedAddr, chainId, userAddr, pointToken)` | `GET /user` |
|
|
224
|
-
| `
|
|
225
|
-
| `
|
|
226
|
-
| `
|
|
227
|
-
| `
|
|
228
|
-
| `
|
|
229
|
-
| `
|
|
230
|
-
| `
|
|
231
|
-
| `
|
|
232
|
-
| `
|
|
233
|
-
|
|
234
|
-
> `swap()` and `quote()` removed in 0.6.0 — see `@pafi-dev/trading`.
|
|
235
|
-
> `config()` and `gasFee()` are optional read endpoints; FE can call
|
|
236
|
-
> `getContractAddresses()` and `quoteOperatorFeeUsdt()` from
|
|
237
|
-
> `@pafi-dev/core` directly with no backend round-trip.
|
|
255
|
+
| Method | HTTP route | Notes |
|
|
256
|
+
| --- | --- | --- |
|
|
257
|
+
| `pools(authedAddr, chainId, pointToken)` | `GET /pools` | |
|
|
258
|
+
| `user(authedAddr, chainId, userAddr, pointToken)` | `GET /user` | |
|
|
259
|
+
| `config(chainId)` | `GET /config` | Includes `mintFeeBpsByToken` + `contracts.mintFeeWrapper` |
|
|
260
|
+
| `claim({ ...nonces })` | `POST /claim` (web — sync `calls[]`) | |
|
|
261
|
+
| `redeem({ amount, aaNonce, ... })` | `POST /redeem` | |
|
|
262
|
+
| `perpDeposit({ amount, brokerId, aaNonce, ... })` | `POST /perp-deposit` | |
|
|
263
|
+
| `claimPrepare(...)` / `claimSubmit(...)` | Mobile claim flow | wrapper-aware |
|
|
264
|
+
| `redeemPrepare(...)` / `redeemSubmit(...)` | Mobile redeem flow | |
|
|
265
|
+
| `claimStatus(authedAddr, lockId)` / `redeemStatus(...)` | Status polling | |
|
|
266
|
+
| `delegateStatus(authedAddr, chainId)` | EIP-7702 — check delegation | |
|
|
267
|
+
| `delegatePrepare(authedAddr, chainId)` | EIP-7702 — build auth hash | |
|
|
268
|
+
| `delegateSubmit({ authSig, ... })` | EIP-7702 — relay empty-batch | |
|
|
238
269
|
|
|
239
270
|
---
|
|
240
271
|
|
|
241
|
-
##
|
|
272
|
+
## Redemption restriction (v0.10+)
|
|
242
273
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
the orchestration:
|
|
274
|
+
Per-issuer policy enforced at `/redeem/prepare` time. Fetched from
|
|
275
|
+
PAFI issuer-api with 5-min cache + fail-open default.
|
|
246
276
|
|
|
247
277
|
```ts
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
278
|
+
import { RedemptionService, PolicyProvider } from "@pafi-dev/issuer";
|
|
279
|
+
import { PostgresRedemptionHistoryStore } from "@pafi-dev/issuer-postgres";
|
|
280
|
+
|
|
281
|
+
const redemption = new RedemptionService({
|
|
282
|
+
policyProvider: new PolicyProvider({
|
|
283
|
+
chainId: 8453,
|
|
284
|
+
issuerId: "gg56",
|
|
285
|
+
apiKey: process.env.PAFI_API_KEY,
|
|
286
|
+
}),
|
|
287
|
+
historyStore: new PostgresRedemptionHistoryStore(dataSource),
|
|
288
|
+
});
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Wire to `createIssuerService({ redemption: {...} })`. Adapter exposes
|
|
292
|
+
`/redemption/preview` + `/redemption/evaluate` automatically.
|
|
293
|
+
|
|
294
|
+
---
|
|
251
295
|
|
|
252
|
-
|
|
296
|
+
## Mobile prepare/submit flow
|
|
253
297
|
|
|
254
|
-
|
|
255
|
-
|
|
298
|
+
```ts
|
|
299
|
+
// 1. mobile → POST /claim/prepare → backend runs:
|
|
300
|
+
const prepared = await api.claimPrepare({
|
|
301
|
+
authenticatedAddress, chainId, pointTokenAddress, amount, aaNonce, mintRequestNonce,
|
|
302
|
+
});
|
|
303
|
+
// returns: {
|
|
304
|
+
// lockId, userOpHash, typedData,
|
|
305
|
+
// userOpHashFallback, typedDataFallback,
|
|
306
|
+
// sponsored, // true if paymaster signed; false → use fallback
|
|
307
|
+
// needsDelegation, // true if user EOA not delegated yet
|
|
308
|
+
// feeAmount, signatureDeadline, expiresInSeconds,
|
|
309
|
+
// }
|
|
310
|
+
|
|
311
|
+
// 2. mobile signs typedData via Privy/MetaMask signTypedData_v4
|
|
312
|
+
// (NOT personal_sign — Pimlico Simple7702Account does raw ecrecover)
|
|
313
|
+
// If `sponsored: false`, sign `typedDataFallback` instead
|
|
314
|
+
|
|
315
|
+
// 3. mobile → POST /claim/submit:
|
|
316
|
+
const result = await api.claimSubmit({
|
|
317
|
+
authenticatedAddress, lockId, signature,
|
|
318
|
+
variant: prepared.sponsored ? "sponsored" : "fallback",
|
|
319
|
+
});
|
|
256
320
|
// returns: { userOpHash } — bundler hash for status polling
|
|
257
321
|
```
|
|
258
322
|
|
|
259
323
|
`handleMobileSubmit` enforces ownership: `entry.sender ===
|
|
260
|
-
authenticatedAddress`.
|
|
261
|
-
pending UserOp once they leak/guess the lockId.
|
|
324
|
+
authenticatedAddress`. Lock has 15-min TTL.
|
|
262
325
|
|
|
263
326
|
---
|
|
264
327
|
|
|
265
|
-
##
|
|
328
|
+
## PointIndexer modes
|
|
266
329
|
|
|
267
330
|
```ts
|
|
268
|
-
//
|
|
269
|
-
const
|
|
270
|
-
|
|
331
|
+
// Default — auto-resolves wrapper from chainId
|
|
332
|
+
const service = createIssuerService({
|
|
333
|
+
chainId: 8453,
|
|
334
|
+
// ...
|
|
335
|
+
indexer: { autoStart: true, pollIntervalMs: 5000 },
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
// Indexer listens to:
|
|
339
|
+
// - mode wrapper: MintFeeWrapper.MintWithFee filtered by pointToken
|
|
340
|
+
// (when wrapper is configured at chainId)
|
|
341
|
+
// - mode direct: PointToken.Transfer(0x0 → user) (legacy / no wrapper)
|
|
271
342
|
```
|
|
272
343
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
344
|
+
Override for fork tests:
|
|
345
|
+
```ts
|
|
346
|
+
indexer: { mintFeeWrapperAddress: "0x000...dead" } // force direct mode
|
|
347
|
+
```
|
|
277
348
|
|
|
278
349
|
---
|
|
279
350
|
|
|
280
351
|
## Error classes
|
|
281
352
|
|
|
282
|
-
All SDK errors inherit `PafiSdkError`. Subclasses +
|
|
353
|
+
All SDK errors inherit `PafiSdkError`. Subclasses + HTTP mapping:
|
|
283
354
|
|
|
284
355
|
| Error | `httpStatus` | `safeToRetry` |
|
|
285
356
|
| --- | --- | --- |
|
|
286
357
|
| `PendingUserOpNotFoundError` | `not_found` | false |
|
|
287
358
|
| `PendingUserOpForbiddenError` | `forbidden` | false |
|
|
288
359
|
| `LockNotFoundError` | `not_found` | false |
|
|
289
|
-
| `IssuerStateError` | `unprocessable` | true if
|
|
360
|
+
| `IssuerStateError` (`ISSUER_NOT_REGISTERED` / `ISSUER_INACTIVE` / `MINT_CAP_EXCEEDED`) | `unprocessable` | true if cap exceeded |
|
|
290
361
|
| `PerpDepositError` | `unprocessable` | true if `RELAY_FEE_EXCEEDS_AMOUNT` |
|
|
291
362
|
| `PTClaimError`, `PTRedeemError` | `unprocessable` | false |
|
|
292
363
|
| `BundlerNotConfiguredError` | `service_unavailable` | false |
|
|
293
364
|
| `BundlerRejectedError` | `unprocessable` | false |
|
|
365
|
+
| `RedemptionPolicyError` (`REDEMPTION_DENIED` / `RATE_LIMIT_EXCEEDED` / ...) | `unprocessable` | varies |
|
|
294
366
|
|
|
295
367
|
---
|
|
296
368
|
|
|
369
|
+
## References
|
|
370
|
+
|
|
371
|
+
- Architecture: [`ARCHITECTURE.md`](../../ARCHITECTURE.md) at SDK root
|
|
372
|
+
- Fee flow & math: [`docs/FEE_FLOW.md`](../../../docs/FEE_FLOW.md)
|
|
373
|
+
|
|
297
374
|
## License
|
|
298
375
|
|
|
299
376
|
Apache-2.0
|