@pafi-dev/issuer 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +299 -160
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +63 -7
- package/dist/index.d.ts +63 -7
- package/dist/index.js +296 -160
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -13,6 +13,26 @@ var PafiSdkError = class extends Error {
|
|
|
13
13
|
this.name = new.target.name;
|
|
14
14
|
}
|
|
15
15
|
};
|
|
16
|
+
var ValidationError = class extends PafiSdkError {
|
|
17
|
+
httpStatus = "unprocessable";
|
|
18
|
+
code;
|
|
19
|
+
details;
|
|
20
|
+
constructor(code, message, details) {
|
|
21
|
+
super(message);
|
|
22
|
+
this.code = code;
|
|
23
|
+
this.details = details;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
var ConfigurationError = class extends PafiSdkError {
|
|
27
|
+
httpStatus = "service_unavailable";
|
|
28
|
+
code;
|
|
29
|
+
details;
|
|
30
|
+
constructor(code, message, details) {
|
|
31
|
+
super(message);
|
|
32
|
+
this.code = code;
|
|
33
|
+
this.details = details;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
16
36
|
|
|
17
37
|
// src/policy/defaultPolicy.ts
|
|
18
38
|
var DefaultPolicyEngine = class {
|
|
@@ -183,12 +203,32 @@ import { getAddress as getAddress2 } from "viem";
|
|
|
183
203
|
import { parseLoginMessage, verifyLoginMessage } from "@pafi-dev/core";
|
|
184
204
|
|
|
185
205
|
// src/auth/errors.ts
|
|
186
|
-
|
|
206
|
+
function statusForCode(code) {
|
|
207
|
+
switch (code) {
|
|
208
|
+
case "INVALID_MESSAGE":
|
|
209
|
+
case "DOMAIN_MISMATCH":
|
|
210
|
+
case "CHAIN_MISMATCH":
|
|
211
|
+
case "MESSAGE_EXPIRED":
|
|
212
|
+
case "MESSAGE_NOT_YET_VALID":
|
|
213
|
+
case "MALFORMED_TOKEN":
|
|
214
|
+
return "unprocessable";
|
|
215
|
+
case "NONCE_INVALID":
|
|
216
|
+
case "SIGNATURE_INVALID":
|
|
217
|
+
case "MISSING_TOKEN":
|
|
218
|
+
case "TOKEN_INVALID":
|
|
219
|
+
case "TOKEN_EXPIRED":
|
|
220
|
+
return "forbidden";
|
|
221
|
+
case "SESSION_REVOKED":
|
|
222
|
+
return "not_found";
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
var AuthError = class extends PafiSdkError {
|
|
187
226
|
code;
|
|
227
|
+
httpStatus;
|
|
188
228
|
constructor(code, message) {
|
|
189
229
|
super(message);
|
|
190
|
-
this.name = "AuthError";
|
|
191
230
|
this.code = code;
|
|
231
|
+
this.httpStatus = statusForCode(code);
|
|
192
232
|
}
|
|
193
233
|
};
|
|
194
234
|
|
|
@@ -385,14 +425,15 @@ async function authenticateRequest(authHeader, authService) {
|
|
|
385
425
|
}
|
|
386
426
|
|
|
387
427
|
// src/relay/types.ts
|
|
388
|
-
var RelayError = class extends
|
|
428
|
+
var RelayError = class extends PafiSdkError {
|
|
429
|
+
httpStatus = "unprocessable";
|
|
389
430
|
code;
|
|
390
|
-
cause;
|
|
391
431
|
constructor(code, message, cause) {
|
|
392
432
|
super(message);
|
|
393
|
-
this.name = "RelayError";
|
|
394
433
|
this.code = code;
|
|
395
|
-
if (cause !== void 0)
|
|
434
|
+
if (cause !== void 0) {
|
|
435
|
+
this.cause = cause;
|
|
436
|
+
}
|
|
396
437
|
}
|
|
397
438
|
};
|
|
398
439
|
|
|
@@ -1107,13 +1148,16 @@ var IssuerApiHandlers = class {
|
|
|
1107
1148
|
/** `POST /auth/login` */
|
|
1108
1149
|
async handleLogin(body) {
|
|
1109
1150
|
if (!body || typeof body.message !== "string" || body.message.length === 0 || typeof body.signature !== "string" || body.signature.length <= 2) {
|
|
1110
|
-
throw new
|
|
1151
|
+
throw new ValidationError(
|
|
1152
|
+
"INVALID_LOGIN_BODY",
|
|
1153
|
+
"handleLogin: message and signature are required"
|
|
1154
|
+
);
|
|
1111
1155
|
}
|
|
1112
1156
|
if (body.message.length > 4096) {
|
|
1113
|
-
throw new
|
|
1157
|
+
throw new ValidationError("MESSAGE_TOO_LONG", "message too long");
|
|
1114
1158
|
}
|
|
1115
1159
|
if (body.signature.length > 260) {
|
|
1116
|
-
throw new
|
|
1160
|
+
throw new ValidationError("SIGNATURE_TOO_LONG", "signature too long");
|
|
1117
1161
|
}
|
|
1118
1162
|
const result = await this.authService.login(body.message, body.signature);
|
|
1119
1163
|
return {
|
|
@@ -1130,11 +1174,15 @@ var IssuerApiHandlers = class {
|
|
|
1130
1174
|
*/
|
|
1131
1175
|
async handleConfig(chainId) {
|
|
1132
1176
|
if (!Number.isInteger(chainId) || chainId <= 0) {
|
|
1133
|
-
throw new
|
|
1177
|
+
throw new ValidationError("INVALID_CHAIN_ID", "invalid chainId", {
|
|
1178
|
+
chainId
|
|
1179
|
+
});
|
|
1134
1180
|
}
|
|
1135
1181
|
if (chainId !== this.chainId) {
|
|
1136
|
-
throw new
|
|
1137
|
-
|
|
1182
|
+
throw new ValidationError(
|
|
1183
|
+
"UNSUPPORTED_CHAIN_ID",
|
|
1184
|
+
`handleConfig: unsupported chainId ${chainId}`,
|
|
1185
|
+
{ requested: chainId, supported: this.chainId }
|
|
1138
1186
|
);
|
|
1139
1187
|
}
|
|
1140
1188
|
const contracts = {
|
|
@@ -1151,7 +1199,8 @@ var IssuerApiHandlers = class {
|
|
|
1151
1199
|
/** `GET /gas-fee` — quoted in USDT (6-decimal base units). */
|
|
1152
1200
|
async handleGasFee() {
|
|
1153
1201
|
if (!this.feeManager) {
|
|
1154
|
-
throw new
|
|
1202
|
+
throw new ConfigurationError(
|
|
1203
|
+
"FEE_MANAGER_NOT_CONFIGURED",
|
|
1155
1204
|
"handleGasFee: feeManager is not configured on this issuer"
|
|
1156
1205
|
);
|
|
1157
1206
|
}
|
|
@@ -1173,13 +1222,16 @@ var IssuerApiHandlers = class {
|
|
|
1173
1222
|
*/
|
|
1174
1223
|
async handlePools(_userAddress, request) {
|
|
1175
1224
|
if (!this.poolsProvider) {
|
|
1176
|
-
throw new
|
|
1225
|
+
throw new ConfigurationError(
|
|
1226
|
+
"POOLS_PROVIDER_NOT_CONFIGURED",
|
|
1177
1227
|
"handlePools: poolsProvider is not configured on this issuer"
|
|
1178
1228
|
);
|
|
1179
1229
|
}
|
|
1180
1230
|
if (request.chainId !== this.chainId) {
|
|
1181
|
-
throw new
|
|
1182
|
-
|
|
1231
|
+
throw new ValidationError(
|
|
1232
|
+
"UNSUPPORTED_CHAIN_ID",
|
|
1233
|
+
`handlePools: unsupported chainId ${request.chainId}`,
|
|
1234
|
+
{ requested: request.chainId, supported: this.chainId }
|
|
1183
1235
|
);
|
|
1184
1236
|
}
|
|
1185
1237
|
return this.poolsProvider(request);
|
|
@@ -1193,21 +1245,27 @@ var IssuerApiHandlers = class {
|
|
|
1193
1245
|
*/
|
|
1194
1246
|
async handleUser(userAddress, request) {
|
|
1195
1247
|
if (request.chainId !== this.chainId) {
|
|
1196
|
-
throw new
|
|
1197
|
-
|
|
1248
|
+
throw new ValidationError(
|
|
1249
|
+
"UNSUPPORTED_CHAIN_ID",
|
|
1250
|
+
`handleUser: unsupported chainId ${request.chainId}`,
|
|
1251
|
+
{ requested: request.chainId, supported: this.chainId }
|
|
1198
1252
|
);
|
|
1199
1253
|
}
|
|
1200
1254
|
const normalizedAuthed = getAddress5(userAddress);
|
|
1201
1255
|
const normalizedRequest = getAddress5(request.userAddress);
|
|
1202
1256
|
if (normalizedAuthed !== normalizedRequest) {
|
|
1203
|
-
throw new
|
|
1204
|
-
"
|
|
1257
|
+
throw new ValidationError(
|
|
1258
|
+
"USER_ADDRESS_MISMATCH",
|
|
1259
|
+
"handleUser: request userAddress must match authenticated user",
|
|
1260
|
+
{ authenticated: normalizedAuthed, requested: normalizedRequest }
|
|
1205
1261
|
);
|
|
1206
1262
|
}
|
|
1207
1263
|
const pointToken = getAddress5(request.pointTokenAddress);
|
|
1208
1264
|
if (!this.supportedTokens.has(pointToken)) {
|
|
1209
|
-
throw new
|
|
1210
|
-
|
|
1265
|
+
throw new ValidationError(
|
|
1266
|
+
"UNSUPPORTED_POINT_TOKEN",
|
|
1267
|
+
`handleUser: unsupported pointToken ${pointToken}`,
|
|
1268
|
+
{ requested: pointToken }
|
|
1211
1269
|
);
|
|
1212
1270
|
}
|
|
1213
1271
|
const [mintRequestNonce, receiverConsentNonce, offChainBalance, onChainBalance, minter] = await Promise.all([
|
|
@@ -1408,69 +1466,82 @@ var PTRedeemHandler = class {
|
|
|
1408
1466
|
this.redeemLockDurationMs,
|
|
1409
1467
|
this.pointTokenAddress
|
|
1410
1468
|
);
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
userAddress: request.userAddress,
|
|
1414
|
-
aaNonce: request.aaNonce,
|
|
1415
|
-
pointTokenAddress: this.pointTokenAddress,
|
|
1416
|
-
batchExecutorAddress: this.batchExecutorAddress,
|
|
1417
|
-
burnRequest: sponsoredBurnRequest,
|
|
1418
|
-
burnerSignature: sponsoredSig,
|
|
1419
|
-
feeAmount: fee,
|
|
1420
|
-
feeRecipient
|
|
1421
|
-
});
|
|
1422
|
-
let fallback = void 0;
|
|
1423
|
-
if (fee > 0n) {
|
|
1424
|
-
const fallbackBurnRequest = {
|
|
1425
|
-
from: request.userAddress,
|
|
1426
|
-
amount: request.amount,
|
|
1427
|
-
nonce: burnNonce,
|
|
1428
|
-
deadline
|
|
1429
|
-
};
|
|
1430
|
-
let fallbackSig;
|
|
1431
|
-
try {
|
|
1432
|
-
fallbackSig = (await signBurnRequest(this.burnerSignerWallet, domain, fallbackBurnRequest)).serialized;
|
|
1433
|
-
} catch (err) {
|
|
1434
|
-
throw new PTRedeemError(
|
|
1435
|
-
"SIGNING_FAILED",
|
|
1436
|
-
`failed to sign fallback BurnRequest: ${err instanceof Error ? err.message : String(err)}`
|
|
1437
|
-
);
|
|
1438
|
-
}
|
|
1439
|
-
const fallbackLockId = await this.ledger.reservePendingCredit(
|
|
1440
|
-
request.userAddress,
|
|
1441
|
-
request.amount,
|
|
1442
|
-
this.redeemLockDurationMs,
|
|
1443
|
-
this.pointTokenAddress
|
|
1444
|
-
);
|
|
1445
|
-
const fallbackUserOp = await this.relayService.prepareBurn({
|
|
1469
|
+
try {
|
|
1470
|
+
const sponsoredUserOp = await this.relayService.prepareBurn({
|
|
1446
1471
|
mode: "burnWithSig",
|
|
1447
1472
|
userAddress: request.userAddress,
|
|
1448
1473
|
aaNonce: request.aaNonce,
|
|
1449
1474
|
pointTokenAddress: this.pointTokenAddress,
|
|
1450
1475
|
batchExecutorAddress: this.batchExecutorAddress,
|
|
1451
|
-
burnRequest:
|
|
1452
|
-
burnerSignature:
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
// auto-quoting RelayService would try to quote a fee here
|
|
1456
|
-
// and re-add the PT.transfer we're trying to strip.
|
|
1457
|
-
feeAmount: 0n
|
|
1476
|
+
burnRequest: sponsoredBurnRequest,
|
|
1477
|
+
burnerSignature: sponsoredSig,
|
|
1478
|
+
feeAmount: fee,
|
|
1479
|
+
feeRecipient
|
|
1458
1480
|
});
|
|
1459
|
-
fallback =
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1481
|
+
let fallback = void 0;
|
|
1482
|
+
if (fee > 0n) {
|
|
1483
|
+
const fallbackBurnRequest = {
|
|
1484
|
+
from: request.userAddress,
|
|
1485
|
+
amount: request.amount,
|
|
1486
|
+
nonce: burnNonce,
|
|
1487
|
+
deadline
|
|
1488
|
+
};
|
|
1489
|
+
let fallbackSig;
|
|
1490
|
+
try {
|
|
1491
|
+
fallbackSig = (await signBurnRequest(this.burnerSignerWallet, domain, fallbackBurnRequest)).serialized;
|
|
1492
|
+
} catch (err) {
|
|
1493
|
+
throw new PTRedeemError(
|
|
1494
|
+
"SIGNING_FAILED",
|
|
1495
|
+
`failed to sign fallback BurnRequest: ${err instanceof Error ? err.message : String(err)}`
|
|
1496
|
+
);
|
|
1497
|
+
}
|
|
1498
|
+
const fallbackLockId = await this.ledger.reservePendingCredit(
|
|
1499
|
+
request.userAddress,
|
|
1500
|
+
request.amount,
|
|
1501
|
+
this.redeemLockDurationMs,
|
|
1502
|
+
this.pointTokenAddress
|
|
1503
|
+
);
|
|
1504
|
+
let fallbackUserOp;
|
|
1505
|
+
try {
|
|
1506
|
+
fallbackUserOp = await this.relayService.prepareBurn({
|
|
1507
|
+
mode: "burnWithSig",
|
|
1508
|
+
userAddress: request.userAddress,
|
|
1509
|
+
aaNonce: request.aaNonce,
|
|
1510
|
+
pointTokenAddress: this.pointTokenAddress,
|
|
1511
|
+
batchExecutorAddress: this.batchExecutorAddress,
|
|
1512
|
+
burnRequest: fallbackBurnRequest,
|
|
1513
|
+
burnerSignature: fallbackSig,
|
|
1514
|
+
// Explicit 0n — fallback is fee-free regardless of how
|
|
1515
|
+
// RelayService is configured. Without this, an
|
|
1516
|
+
// auto-quoting RelayService would try to quote a fee here
|
|
1517
|
+
// and re-add the PT.transfer we're trying to strip.
|
|
1518
|
+
feeAmount: 0n
|
|
1519
|
+
});
|
|
1520
|
+
} catch (err) {
|
|
1521
|
+
await this.ledger.releaseLock(fallbackLockId).catch(() => {
|
|
1522
|
+
});
|
|
1523
|
+
throw err;
|
|
1524
|
+
}
|
|
1525
|
+
fallback = {
|
|
1526
|
+
lockId: fallbackLockId,
|
|
1527
|
+
userOp: fallbackUserOp,
|
|
1528
|
+
netCreditAmount: request.amount
|
|
1529
|
+
};
|
|
1530
|
+
}
|
|
1531
|
+
return {
|
|
1532
|
+
lockId: sponsoredLockId,
|
|
1533
|
+
userOp: sponsoredUserOp,
|
|
1534
|
+
netCreditAmount: sponsoredBurnAmount,
|
|
1535
|
+
feeAmount: fee,
|
|
1536
|
+
fallback,
|
|
1537
|
+
expiresInSeconds: Math.floor(this.redeemLockDurationMs / 1e3),
|
|
1538
|
+
signatureDeadline: deadline
|
|
1463
1539
|
};
|
|
1540
|
+
} catch (err) {
|
|
1541
|
+
await this.ledger.releaseLock(sponsoredLockId).catch(() => {
|
|
1542
|
+
});
|
|
1543
|
+
throw err;
|
|
1464
1544
|
}
|
|
1465
|
-
return {
|
|
1466
|
-
lockId: sponsoredLockId,
|
|
1467
|
-
userOp: sponsoredUserOp,
|
|
1468
|
-
netCreditAmount: sponsoredBurnAmount,
|
|
1469
|
-
feeAmount: fee,
|
|
1470
|
-
fallback,
|
|
1471
|
-
expiresInSeconds: Math.floor(this.redeemLockDurationMs / 1e3),
|
|
1472
|
-
signatureDeadline: deadline
|
|
1473
|
-
};
|
|
1474
1545
|
}
|
|
1475
1546
|
};
|
|
1476
1547
|
|
|
@@ -1744,6 +1815,41 @@ async function prepareMobileUserOp(params) {
|
|
|
1744
1815
|
};
|
|
1745
1816
|
}
|
|
1746
1817
|
|
|
1818
|
+
// src/pafi-backend/types.ts
|
|
1819
|
+
var PafiBackendError = class extends Error {
|
|
1820
|
+
constructor(code, message, httpStatus, details, opts) {
|
|
1821
|
+
super(message);
|
|
1822
|
+
this.code = code;
|
|
1823
|
+
this.httpStatus = httpStatus;
|
|
1824
|
+
this.details = details;
|
|
1825
|
+
this.name = "PafiBackendError";
|
|
1826
|
+
if (opts?.retryAfter !== void 0) this.retryAfter = opts.retryAfter;
|
|
1827
|
+
if (opts?.safeToRetry !== void 0) this.serverSafeToRetry = opts.safeToRetry;
|
|
1828
|
+
}
|
|
1829
|
+
code;
|
|
1830
|
+
httpStatus;
|
|
1831
|
+
details;
|
|
1832
|
+
retryAfter;
|
|
1833
|
+
serverSafeToRetry;
|
|
1834
|
+
get safeToRetry() {
|
|
1835
|
+
if (this.serverSafeToRetry !== void 0) return this.serverSafeToRetry;
|
|
1836
|
+
switch (this.code) {
|
|
1837
|
+
case "RATE_LIMITER_UNAVAILABLE":
|
|
1838
|
+
case "INTERNAL_ERROR":
|
|
1839
|
+
case "TIMEOUT":
|
|
1840
|
+
case "NETWORK_ERROR":
|
|
1841
|
+
return true;
|
|
1842
|
+
case "RATE_LIMIT_EXCEEDED":
|
|
1843
|
+
case "RATE_LIMIT_EXCEEDED_DAILY":
|
|
1844
|
+
case "RATE_LIMIT_EXCEEDED_PER_USER":
|
|
1845
|
+
case "ISSUER_BUDGET_EXCEEDED":
|
|
1846
|
+
return true;
|
|
1847
|
+
default:
|
|
1848
|
+
return false;
|
|
1849
|
+
}
|
|
1850
|
+
}
|
|
1851
|
+
};
|
|
1852
|
+
|
|
1747
1853
|
// src/pafi-backend/helpers.ts
|
|
1748
1854
|
var BundlerNotConfiguredError = class extends PafiSdkError {
|
|
1749
1855
|
code = "BUNDLER_NOT_CONFIGURED";
|
|
@@ -1779,8 +1885,23 @@ async function requestPaymaster(params) {
|
|
|
1779
1885
|
});
|
|
1780
1886
|
} catch (err) {
|
|
1781
1887
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1782
|
-
|
|
1783
|
-
|
|
1888
|
+
if (err instanceof PafiBackendError && isTransientPaymasterError(err.code)) {
|
|
1889
|
+
params.onWarning?.(`Paymaster sponsorship declined (transient): ${msg}`);
|
|
1890
|
+
return void 0;
|
|
1891
|
+
}
|
|
1892
|
+
throw err;
|
|
1893
|
+
}
|
|
1894
|
+
}
|
|
1895
|
+
function isTransientPaymasterError(code) {
|
|
1896
|
+
switch (code) {
|
|
1897
|
+
case "NETWORK_ERROR":
|
|
1898
|
+
case "TIMEOUT":
|
|
1899
|
+
case "PAYMASTER_UNAVAILABLE":
|
|
1900
|
+
case "RATE_LIMITER_UNAVAILABLE":
|
|
1901
|
+
case "INTERNAL_ERROR":
|
|
1902
|
+
return true;
|
|
1903
|
+
default:
|
|
1904
|
+
return false;
|
|
1784
1905
|
}
|
|
1785
1906
|
}
|
|
1786
1907
|
function defaultFunctionForScenario(scenario) {
|
|
@@ -1964,39 +2085,19 @@ var PTClaimHandler = class {
|
|
|
1964
2085
|
this.cfg.lockDurationMs,
|
|
1965
2086
|
request.pointTokenAddress
|
|
1966
2087
|
);
|
|
1967
|
-
const signatureDeadline = BigInt(
|
|
1968
|
-
Math.floor(this.cfg.now() / 1e3) + this.cfg.signatureDeadlineSeconds
|
|
1969
|
-
);
|
|
1970
|
-
const feeAmount = this.cfg.feeService ? await this.cfg.feeService.estimateGasFee() : 0n;
|
|
1971
|
-
const domain = {
|
|
1972
|
-
name: this.cfg.pointTokenDomainName,
|
|
1973
|
-
chainId: request.chainId,
|
|
1974
|
-
verifyingContract: request.pointTokenAddress
|
|
1975
|
-
};
|
|
1976
|
-
let userOp;
|
|
1977
2088
|
try {
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
aaNonce: request.aaNonce,
|
|
1981
|
-
batchExecutorAddress,
|
|
1982
|
-
pointTokenAddress: request.pointTokenAddress,
|
|
1983
|
-
amount: request.amount,
|
|
1984
|
-
issuerSignerWallet: this.cfg.issuerSignerWallet,
|
|
1985
|
-
domain,
|
|
1986
|
-
mintRequestNonce: request.mintRequestNonce,
|
|
1987
|
-
deadline: signatureDeadline
|
|
1988
|
-
// No feeAmount/feeRecipient — RelayService auto-resolves.
|
|
1989
|
-
});
|
|
1990
|
-
} catch (err) {
|
|
1991
|
-
throw new PTClaimError(
|
|
1992
|
-
"BUILD_FAILED",
|
|
1993
|
-
`prepareMint failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2089
|
+
const signatureDeadline = BigInt(
|
|
2090
|
+
Math.floor(this.cfg.now() / 1e3) + this.cfg.signatureDeadlineSeconds
|
|
1994
2091
|
);
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
2092
|
+
const feeAmount = this.cfg.feeService ? await this.cfg.feeService.estimateGasFee() : 0n;
|
|
2093
|
+
const domain = {
|
|
2094
|
+
name: this.cfg.pointTokenDomainName,
|
|
2095
|
+
chainId: request.chainId,
|
|
2096
|
+
verifyingContract: request.pointTokenAddress
|
|
2097
|
+
};
|
|
2098
|
+
let userOp;
|
|
1998
2099
|
try {
|
|
1999
|
-
|
|
2100
|
+
userOp = await this.cfg.relayService.prepareMint({
|
|
2000
2101
|
userAddress: request.userAddress,
|
|
2001
2102
|
aaNonce: request.aaNonce,
|
|
2002
2103
|
batchExecutorAddress,
|
|
@@ -2005,28 +2106,54 @@ var PTClaimHandler = class {
|
|
|
2005
2106
|
issuerSignerWallet: this.cfg.issuerSignerWallet,
|
|
2006
2107
|
domain,
|
|
2007
2108
|
mintRequestNonce: request.mintRequestNonce,
|
|
2008
|
-
deadline: signatureDeadline
|
|
2009
|
-
feeAmount
|
|
2109
|
+
deadline: signatureDeadline
|
|
2110
|
+
// No feeAmount/feeRecipient — RelayService auto-resolves.
|
|
2010
2111
|
});
|
|
2011
2112
|
} catch (err) {
|
|
2012
2113
|
throw new PTClaimError(
|
|
2013
2114
|
"BUILD_FAILED",
|
|
2014
|
-
`prepareMint
|
|
2115
|
+
`prepareMint failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2015
2116
|
);
|
|
2016
2117
|
}
|
|
2118
|
+
let fallback;
|
|
2119
|
+
if (feeAmount > 0n) {
|
|
2120
|
+
try {
|
|
2121
|
+
fallback = await this.cfg.relayService.prepareMint({
|
|
2122
|
+
userAddress: request.userAddress,
|
|
2123
|
+
aaNonce: request.aaNonce,
|
|
2124
|
+
batchExecutorAddress,
|
|
2125
|
+
pointTokenAddress: request.pointTokenAddress,
|
|
2126
|
+
amount: request.amount,
|
|
2127
|
+
issuerSignerWallet: this.cfg.issuerSignerWallet,
|
|
2128
|
+
domain,
|
|
2129
|
+
mintRequestNonce: request.mintRequestNonce,
|
|
2130
|
+
deadline: signatureDeadline,
|
|
2131
|
+
feeAmount: 0n
|
|
2132
|
+
});
|
|
2133
|
+
} catch (err) {
|
|
2134
|
+
throw new PTClaimError(
|
|
2135
|
+
"BUILD_FAILED",
|
|
2136
|
+
`prepareMint (fallback) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2137
|
+
);
|
|
2138
|
+
}
|
|
2139
|
+
}
|
|
2140
|
+
const calls = decodeBatchExecuteCalls(userOp.callData);
|
|
2141
|
+
const callsFallback = fallback ? decodeBatchExecuteCalls(fallback.callData) : void 0;
|
|
2142
|
+
return {
|
|
2143
|
+
userOp,
|
|
2144
|
+
fallback,
|
|
2145
|
+
lockId,
|
|
2146
|
+
feeAmount,
|
|
2147
|
+
signatureDeadline,
|
|
2148
|
+
expiresInSeconds: Math.floor(this.cfg.lockDurationMs / 1e3),
|
|
2149
|
+
calls,
|
|
2150
|
+
callsFallback
|
|
2151
|
+
};
|
|
2152
|
+
} catch (err) {
|
|
2153
|
+
await this.cfg.ledger.releaseLock(lockId).catch(() => {
|
|
2154
|
+
});
|
|
2155
|
+
throw err;
|
|
2017
2156
|
}
|
|
2018
|
-
const calls = decodeBatchExecuteCalls(userOp.callData);
|
|
2019
|
-
const callsFallback = fallback ? decodeBatchExecuteCalls(fallback.callData) : void 0;
|
|
2020
|
-
return {
|
|
2021
|
-
userOp,
|
|
2022
|
-
fallback,
|
|
2023
|
-
lockId,
|
|
2024
|
-
feeAmount,
|
|
2025
|
-
signatureDeadline,
|
|
2026
|
-
expiresInSeconds: Math.floor(this.cfg.lockDurationMs / 1e3),
|
|
2027
|
-
calls,
|
|
2028
|
-
callsFallback
|
|
2029
|
-
};
|
|
2030
2157
|
}
|
|
2031
2158
|
};
|
|
2032
2159
|
|
|
@@ -2281,9 +2408,45 @@ import {
|
|
|
2281
2408
|
getContractAddresses as getContractAddresses6,
|
|
2282
2409
|
parseEip7702DelegatedAddress as parseEip7702DelegatedAddress2
|
|
2283
2410
|
} from "@pafi-dev/core";
|
|
2411
|
+
var AdapterMisconfiguredError = class extends Error {
|
|
2412
|
+
code = "ADAPTER_MISCONFIGURED";
|
|
2413
|
+
constructor(message) {
|
|
2414
|
+
super(message);
|
|
2415
|
+
this.name = "AdapterMisconfiguredError";
|
|
2416
|
+
}
|
|
2417
|
+
};
|
|
2284
2418
|
var IssuerApiAdapter = class {
|
|
2285
2419
|
cfg;
|
|
2286
2420
|
constructor(config) {
|
|
2421
|
+
if (config.ptClaimHandler) {
|
|
2422
|
+
if (typeof config.ledger.bindMintUserOpHash !== "function") {
|
|
2423
|
+
throw new AdapterMisconfiguredError(
|
|
2424
|
+
"ledger.bindMintUserOpHash is required when ptClaimHandler is wired (mobile claim flow). Implement it on your IPointLedger or omit ptClaimHandler from IssuerApiAdapter config."
|
|
2425
|
+
);
|
|
2426
|
+
}
|
|
2427
|
+
if (typeof config.ledger.getMintLock !== "function") {
|
|
2428
|
+
throw new AdapterMisconfiguredError(
|
|
2429
|
+
"ledger.getMintLock is required when ptClaimHandler is wired \u2014 claimStatus uses it to look up the lock."
|
|
2430
|
+
);
|
|
2431
|
+
}
|
|
2432
|
+
}
|
|
2433
|
+
if (config.ptRedeemHandler) {
|
|
2434
|
+
if (typeof config.ledger.reservePendingCredit !== "function") {
|
|
2435
|
+
throw new AdapterMisconfiguredError(
|
|
2436
|
+
"ledger.reservePendingCredit is required when ptRedeemHandler is wired (burn/redeem reverse flow). PTRedeemHandler also enforces this at construction; see ledger/types.ts comments."
|
|
2437
|
+
);
|
|
2438
|
+
}
|
|
2439
|
+
if (typeof config.ledger.bindCreditUserOpHash !== "function") {
|
|
2440
|
+
throw new AdapterMisconfiguredError(
|
|
2441
|
+
"ledger.bindCreditUserOpHash is required when ptRedeemHandler is wired (mobile redeem flow)."
|
|
2442
|
+
);
|
|
2443
|
+
}
|
|
2444
|
+
if (typeof config.ledger.getPendingCredit !== "function") {
|
|
2445
|
+
throw new AdapterMisconfiguredError(
|
|
2446
|
+
"ledger.getPendingCredit is required when ptRedeemHandler is wired \u2014 redeemStatus uses it to look up the credit."
|
|
2447
|
+
);
|
|
2448
|
+
}
|
|
2449
|
+
}
|
|
2287
2450
|
this.cfg = config;
|
|
2288
2451
|
}
|
|
2289
2452
|
// ------------------------------ Read endpoints ---------------------------
|
|
@@ -2584,6 +2747,11 @@ var IssuerApiAdapter = class {
|
|
|
2584
2747
|
/**
|
|
2585
2748
|
* Build + sign a SponsorAuth payload. Returns `undefined` when no
|
|
2586
2749
|
* issuer id is configured, so the controller can skip the field.
|
|
2750
|
+
*
|
|
2751
|
+
* v0.7.1 — `scenario` typed as `SponsorshipScenario` (was `string`).
|
|
2752
|
+
* Previously a typo (`"perp_deposit"` vs `"perp-deposit"`) compiled
|
|
2753
|
+
* fine but rejected at L1 by sponsor-relayer's IntentValidator. See
|
|
2754
|
+
* SDK_ISSUER_AUDIT.md N5.
|
|
2587
2755
|
*/
|
|
2588
2756
|
async buildSponsorAuth(authenticatedAddress, callData, chainId, scenario) {
|
|
2589
2757
|
if (!this.cfg.pafiIssuerId) return void 0;
|
|
@@ -3044,41 +3212,6 @@ var BalanceAggregator = class {
|
|
|
3044
3212
|
}
|
|
3045
3213
|
};
|
|
3046
3214
|
|
|
3047
|
-
// src/pafi-backend/types.ts
|
|
3048
|
-
var PafiBackendError = class extends Error {
|
|
3049
|
-
constructor(code, message, httpStatus, details, opts) {
|
|
3050
|
-
super(message);
|
|
3051
|
-
this.code = code;
|
|
3052
|
-
this.httpStatus = httpStatus;
|
|
3053
|
-
this.details = details;
|
|
3054
|
-
this.name = "PafiBackendError";
|
|
3055
|
-
if (opts?.retryAfter !== void 0) this.retryAfter = opts.retryAfter;
|
|
3056
|
-
if (opts?.safeToRetry !== void 0) this.serverSafeToRetry = opts.safeToRetry;
|
|
3057
|
-
}
|
|
3058
|
-
code;
|
|
3059
|
-
httpStatus;
|
|
3060
|
-
details;
|
|
3061
|
-
retryAfter;
|
|
3062
|
-
serverSafeToRetry;
|
|
3063
|
-
get safeToRetry() {
|
|
3064
|
-
if (this.serverSafeToRetry !== void 0) return this.serverSafeToRetry;
|
|
3065
|
-
switch (this.code) {
|
|
3066
|
-
case "RATE_LIMITER_UNAVAILABLE":
|
|
3067
|
-
case "INTERNAL_ERROR":
|
|
3068
|
-
case "TIMEOUT":
|
|
3069
|
-
case "NETWORK_ERROR":
|
|
3070
|
-
return true;
|
|
3071
|
-
case "RATE_LIMIT_EXCEEDED":
|
|
3072
|
-
case "RATE_LIMIT_EXCEEDED_DAILY":
|
|
3073
|
-
case "RATE_LIMIT_EXCEEDED_PER_USER":
|
|
3074
|
-
case "ISSUER_BUDGET_EXCEEDED":
|
|
3075
|
-
return true;
|
|
3076
|
-
default:
|
|
3077
|
-
return false;
|
|
3078
|
-
}
|
|
3079
|
-
}
|
|
3080
|
-
};
|
|
3081
|
-
|
|
3082
3215
|
// src/pafi-backend/client.ts
|
|
3083
3216
|
function serializeBigInt(_key, value) {
|
|
3084
3217
|
return typeof value === "bigint" ? value.toString(10) : value;
|
|
@@ -3523,14 +3656,16 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
3523
3656
|
};
|
|
3524
3657
|
|
|
3525
3658
|
// src/index.ts
|
|
3526
|
-
var PAFI_ISSUER_SDK_VERSION = "0.
|
|
3659
|
+
var PAFI_ISSUER_SDK_VERSION = true ? "0.7.1" : "dev";
|
|
3527
3660
|
export {
|
|
3661
|
+
AdapterMisconfiguredError,
|
|
3528
3662
|
AuthError,
|
|
3529
3663
|
AuthService,
|
|
3530
3664
|
BalanceAggregator,
|
|
3531
3665
|
BundlerNotConfiguredError,
|
|
3532
3666
|
BundlerRejectedError,
|
|
3533
3667
|
BurnIndexer,
|
|
3668
|
+
ConfigurationError,
|
|
3534
3669
|
DefaultPolicyEngine,
|
|
3535
3670
|
FeeManager,
|
|
3536
3671
|
InMemoryCursorStore,
|
|
@@ -3558,6 +3693,7 @@ export {
|
|
|
3558
3693
|
PointIndexer,
|
|
3559
3694
|
RelayError,
|
|
3560
3695
|
RelayService,
|
|
3696
|
+
ValidationError,
|
|
3561
3697
|
authenticateRequest,
|
|
3562
3698
|
createIssuerService,
|
|
3563
3699
|
createNativePtQuoter,
|