@pafi-dev/issuer 0.5.16 → 0.5.18

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.d.cts CHANGED
@@ -1129,16 +1129,30 @@ interface PTRedeemRequest {
1129
1129
  feeRecipient?: Address;
1130
1130
  }
1131
1131
  interface PTRedeemResponse {
1132
- /** Lock id from the ledger — client polls status with this. */
1133
- lockId: string;
1134
- /** Unsigned UserOp — FE attaches paymaster + user signature + submits. */
1135
- userOp: PartialUserOperation;
1136
1132
  /**
1137
- * Actual burn amount signed in BurnRequest (= request.amount - feeAmount).
1138
- * Equals what BurnIndexer credits off-chain. FE uses this as the user-
1139
- * facing "amount you'll receive" figure.
1133
+ * Sponsored path UserOp with PT fee transfer. BurnRequest signed for
1134
+ * `request.amount - feeAmount`. User holds exactly `request.amount` PT
1135
+ * and the fee comes out of the redeem amount, NOT on top.
1140
1136
  */
1137
+ lockId: string;
1138
+ userOp: PartialUserOperation;
1139
+ /** = request.amount - feeAmount. What BurnIndexer credits off-chain on sponsored fire. */
1141
1140
  netCreditAmount: bigint;
1141
+ /**
1142
+ * Fallback path — UserOp with NO fee transfer. BurnRequest signed for
1143
+ * full `request.amount`. User pays gas in ETH directly. Present only
1144
+ * when `feeAmount > 0`.
1145
+ *
1146
+ * Same nonce as sponsored: only one of the two can fire on-chain;
1147
+ * the other lock auto-expires after `expiresInSeconds`. BurnIndexer
1148
+ * matches by burn amount and resolves the correct lock.
1149
+ */
1150
+ fallback?: {
1151
+ lockId: string;
1152
+ userOp: PartialUserOperation;
1153
+ /** = request.amount. Full credit when fallback fires. */
1154
+ netCreditAmount: bigint;
1155
+ };
1142
1156
  /** Seconds until the lock expires if the burn doesn't land. */
1143
1157
  expiresInSeconds: number;
1144
1158
  /** The BurnRequest deadline (unix seconds) — FE uses this to surface a countdown. */
package/dist/index.d.ts CHANGED
@@ -1129,16 +1129,30 @@ interface PTRedeemRequest {
1129
1129
  feeRecipient?: Address;
1130
1130
  }
1131
1131
  interface PTRedeemResponse {
1132
- /** Lock id from the ledger — client polls status with this. */
1133
- lockId: string;
1134
- /** Unsigned UserOp — FE attaches paymaster + user signature + submits. */
1135
- userOp: PartialUserOperation;
1136
1132
  /**
1137
- * Actual burn amount signed in BurnRequest (= request.amount - feeAmount).
1138
- * Equals what BurnIndexer credits off-chain. FE uses this as the user-
1139
- * facing "amount you'll receive" figure.
1133
+ * Sponsored path UserOp with PT fee transfer. BurnRequest signed for
1134
+ * `request.amount - feeAmount`. User holds exactly `request.amount` PT
1135
+ * and the fee comes out of the redeem amount, NOT on top.
1140
1136
  */
1137
+ lockId: string;
1138
+ userOp: PartialUserOperation;
1139
+ /** = request.amount - feeAmount. What BurnIndexer credits off-chain on sponsored fire. */
1141
1140
  netCreditAmount: bigint;
1141
+ /**
1142
+ * Fallback path — UserOp with NO fee transfer. BurnRequest signed for
1143
+ * full `request.amount`. User pays gas in ETH directly. Present only
1144
+ * when `feeAmount > 0`.
1145
+ *
1146
+ * Same nonce as sponsored: only one of the two can fire on-chain;
1147
+ * the other lock auto-expires after `expiresInSeconds`. BurnIndexer
1148
+ * matches by burn amount and resolves the correct lock.
1149
+ */
1150
+ fallback?: {
1151
+ lockId: string;
1152
+ userOp: PartialUserOperation;
1153
+ /** = request.amount. Full credit when fallback fires. */
1154
+ netCreditAmount: bigint;
1155
+ };
1142
1156
  /** Seconds until the lock expires if the burn doesn't land. */
1143
1157
  expiresInSeconds: number;
1144
1158
  /** The BurnRequest deadline (unix seconds) — FE uses this to surface a countdown. */
package/dist/index.js CHANGED
@@ -1379,8 +1379,6 @@ var PTRedeemHandler = class {
1379
1379
  `fee (${fee}) must be strictly less than redeem amount (${request.amount})`
1380
1380
  );
1381
1381
  }
1382
- const burnAmount = request.amount - fee;
1383
- const netCreditAmount = burnAmount;
1384
1382
  const onChainBalance = await getPointTokenBalance2(
1385
1383
  this.provider,
1386
1384
  this.pointTokenAddress,
@@ -1400,47 +1398,83 @@ var PTRedeemHandler = class {
1400
1398
  chainId: this.chainId,
1401
1399
  verifyingContract: this.domain.verifyingContract ?? this.pointTokenAddress
1402
1400
  };
1403
- const burnRequest = {
1401
+ const sponsoredBurnAmount = request.amount - fee;
1402
+ const sponsoredBurnRequest = {
1404
1403
  from: request.userAddress,
1405
- amount: burnAmount,
1404
+ amount: sponsoredBurnAmount,
1406
1405
  nonce: burnNonce,
1407
1406
  deadline
1408
1407
  };
1409
- let burnerSignature;
1408
+ let sponsoredSig;
1410
1409
  try {
1411
- const sig = await signBurnRequest(
1412
- this.burnerSignerWallet,
1413
- domain,
1414
- burnRequest
1415
- );
1416
- burnerSignature = sig.serialized;
1410
+ sponsoredSig = (await signBurnRequest(this.burnerSignerWallet, domain, sponsoredBurnRequest)).serialized;
1417
1411
  } catch (err) {
1418
1412
  throw new PTRedeemError(
1419
1413
  "SIGNING_FAILED",
1420
- `failed to sign BurnRequest: ${err instanceof Error ? err.message : String(err)}`
1414
+ `failed to sign sponsored BurnRequest: ${err instanceof Error ? err.message : String(err)}`
1421
1415
  );
1422
1416
  }
1423
- const lockId = await this.ledger.reservePendingCredit(
1417
+ const sponsoredLockId = await this.ledger.reservePendingCredit(
1424
1418
  request.userAddress,
1425
- netCreditAmount,
1419
+ sponsoredBurnAmount,
1426
1420
  this.redeemLockDurationMs,
1427
1421
  this.pointTokenAddress
1428
1422
  );
1429
- const userOp = this.relayService.prepareBurn({
1423
+ const sponsoredUserOp = this.relayService.prepareBurn({
1430
1424
  mode: "burnWithSig",
1431
1425
  userAddress: request.userAddress,
1432
1426
  aaNonce: request.aaNonce,
1433
1427
  pointTokenAddress: this.pointTokenAddress,
1434
1428
  batchExecutorAddress: this.batchExecutorAddress,
1435
- burnRequest,
1436
- burnerSignature,
1429
+ burnRequest: sponsoredBurnRequest,
1430
+ burnerSignature: sponsoredSig,
1437
1431
  feeAmount: fee,
1438
1432
  feeRecipient: request.feeRecipient
1439
1433
  });
1434
+ let fallback = void 0;
1435
+ if (fee > 0n) {
1436
+ const fallbackBurnRequest = {
1437
+ from: request.userAddress,
1438
+ amount: request.amount,
1439
+ nonce: burnNonce,
1440
+ deadline
1441
+ };
1442
+ let fallbackSig;
1443
+ try {
1444
+ fallbackSig = (await signBurnRequest(this.burnerSignerWallet, domain, fallbackBurnRequest)).serialized;
1445
+ } catch (err) {
1446
+ throw new PTRedeemError(
1447
+ "SIGNING_FAILED",
1448
+ `failed to sign fallback BurnRequest: ${err instanceof Error ? err.message : String(err)}`
1449
+ );
1450
+ }
1451
+ const fallbackLockId = await this.ledger.reservePendingCredit(
1452
+ request.userAddress,
1453
+ request.amount,
1454
+ this.redeemLockDurationMs,
1455
+ this.pointTokenAddress
1456
+ );
1457
+ const fallbackUserOp = this.relayService.prepareBurn({
1458
+ mode: "burnWithSig",
1459
+ userAddress: request.userAddress,
1460
+ aaNonce: request.aaNonce,
1461
+ pointTokenAddress: this.pointTokenAddress,
1462
+ batchExecutorAddress: this.batchExecutorAddress,
1463
+ burnRequest: fallbackBurnRequest,
1464
+ burnerSignature: fallbackSig
1465
+ // No feeAmount/feeRecipient — fallback is fee-free.
1466
+ });
1467
+ fallback = {
1468
+ lockId: fallbackLockId,
1469
+ userOp: fallbackUserOp,
1470
+ netCreditAmount: request.amount
1471
+ };
1472
+ }
1440
1473
  return {
1441
- lockId,
1442
- userOp,
1443
- netCreditAmount,
1474
+ lockId: sponsoredLockId,
1475
+ userOp: sponsoredUserOp,
1476
+ netCreditAmount: sponsoredBurnAmount,
1477
+ fallback,
1444
1478
  expiresInSeconds: Math.floor(this.redeemLockDurationMs / 1e3),
1445
1479
  signatureDeadline: deadline
1446
1480
  };