@pafi-dev/issuer 0.3.0-alpha.0 → 0.3.0-beta.1
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 +354 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +208 -2
- package/dist/index.d.ts +208 -2
- package/dist/index.js +338 -5
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -34,12 +34,16 @@ __export(index_exports, {
|
|
|
34
34
|
MintingGatewayError: () => MintingGatewayError,
|
|
35
35
|
NonceManager: () => NonceManager,
|
|
36
36
|
PAFI_ISSUER_SDK_VERSION: () => PAFI_ISSUER_SDK_VERSION,
|
|
37
|
+
PTRedeemError: () => PTRedeemError,
|
|
38
|
+
PTRedeemHandler: () => PTRedeemHandler,
|
|
37
39
|
PafiBackendClient: () => PafiBackendClient,
|
|
38
40
|
PafiBackendError: () => PafiBackendError,
|
|
39
41
|
PointIndexer: () => PointIndexer,
|
|
40
42
|
PrivateKeySigner: () => PrivateKeySigner,
|
|
41
43
|
RelayError: () => RelayError,
|
|
42
44
|
RelayService: () => RelayService,
|
|
45
|
+
TopUpRedemptionError: () => TopUpRedemptionError,
|
|
46
|
+
TopUpRedemptionHandler: () => TopUpRedemptionHandler,
|
|
43
47
|
authenticateRequest: () => authenticateRequest,
|
|
44
48
|
createIssuerService: () => createIssuerService,
|
|
45
49
|
createSubgraphNativeUsdtQuoter: () => createSubgraphNativeUsdtQuoter,
|
|
@@ -630,6 +634,7 @@ var RelayError = class extends Error {
|
|
|
630
634
|
};
|
|
631
635
|
|
|
632
636
|
// src/relay/relayService.ts
|
|
637
|
+
var import_viem5 = require("viem");
|
|
633
638
|
var import_core3 = require("@pafi-dev/core");
|
|
634
639
|
var DEFAULT_CONFIRMATION_TIMEOUT_MS = 6e4;
|
|
635
640
|
var RelayService = class {
|
|
@@ -755,6 +760,154 @@ var RelayService = class {
|
|
|
755
760
|
);
|
|
756
761
|
}
|
|
757
762
|
}
|
|
763
|
+
// ==========================================================================
|
|
764
|
+
// v1.4 — Sponsored UserOp preparation (beta with mocked SC contracts)
|
|
765
|
+
// ==========================================================================
|
|
766
|
+
//
|
|
767
|
+
// These two methods build unsigned `PartialUserOperation` payloads for
|
|
768
|
+
// the Frontend to sign (via Privy) and submit to the Bundler. The
|
|
769
|
+
// Issuer Backend no longer broadcasts — that's the Frontend's job.
|
|
770
|
+
//
|
|
771
|
+
// Uses mocked Relayer v2 + PointToken ABIs from `@pafi-dev/core/contracts`.
|
|
772
|
+
// When SC delivers real ABIs, the imports swap but these method bodies
|
|
773
|
+
// stay the same (calldata encoder is ABI-driven).
|
|
774
|
+
// ==========================================================================
|
|
775
|
+
/**
|
|
776
|
+
* Build an unsigned UserOp for Scenario 1 (Mint).
|
|
777
|
+
*
|
|
778
|
+
* Flow:
|
|
779
|
+
* 1. Encode `Relayer.mint(request, userSig, issuerSig)` as the inner call
|
|
780
|
+
* 2. Optionally append a PT fee transfer from user → feeRecipient
|
|
781
|
+
* (fee recovery happens on-chain via BatchExecutor, not via an
|
|
782
|
+
* operator wallet)
|
|
783
|
+
* 3. Wrap all inner calls into `BatchExecutor.execute(calls[])`
|
|
784
|
+
* 4. Return a `PartialUserOperation` ready for:
|
|
785
|
+
* - gas estimation (Bundler)
|
|
786
|
+
* - paymaster sponsorship (PAFI Backend)
|
|
787
|
+
* - user signature (Privy)
|
|
788
|
+
*/
|
|
789
|
+
prepareMint(params) {
|
|
790
|
+
if (!params.relayerAddress) {
|
|
791
|
+
throw new RelayError("ENCODE_FAILED", "prepareMint: relayerAddress required");
|
|
792
|
+
}
|
|
793
|
+
if (!params.batchExecutorAddress) {
|
|
794
|
+
throw new RelayError(
|
|
795
|
+
"ENCODE_FAILED",
|
|
796
|
+
"prepareMint: batchExecutorAddress required"
|
|
797
|
+
);
|
|
798
|
+
}
|
|
799
|
+
if (!params.userAddress) {
|
|
800
|
+
throw new RelayError("ENCODE_FAILED", "prepareMint: userAddress required");
|
|
801
|
+
}
|
|
802
|
+
let mintCallData;
|
|
803
|
+
try {
|
|
804
|
+
mintCallData = (0, import_viem5.encodeFunctionData)({
|
|
805
|
+
abi: import_core3.RELAYER_V2_ABI,
|
|
806
|
+
functionName: "mint",
|
|
807
|
+
args: [params.mintRequest, params.userSignature, params.issuerSignature]
|
|
808
|
+
});
|
|
809
|
+
} catch (err) {
|
|
810
|
+
throw new RelayError(
|
|
811
|
+
"ENCODE_FAILED",
|
|
812
|
+
`prepareMint: failed to encode Relayer.mint: ${errorMessage(err)}`,
|
|
813
|
+
err
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
const operations = [
|
|
817
|
+
{
|
|
818
|
+
target: params.relayerAddress,
|
|
819
|
+
value: 0n,
|
|
820
|
+
data: mintCallData
|
|
821
|
+
}
|
|
822
|
+
];
|
|
823
|
+
if (params.mintRequest.feeAmount > 0n) {
|
|
824
|
+
operations.push({
|
|
825
|
+
target: params.pointTokenAddress,
|
|
826
|
+
value: 0n,
|
|
827
|
+
data: (0, import_viem5.encodeFunctionData)({
|
|
828
|
+
abi: import_core3.POINT_TOKEN_V2_ABI,
|
|
829
|
+
functionName: "balanceOf",
|
|
830
|
+
// placeholder — real impl uses transfer
|
|
831
|
+
args: [params.mintRequest.feeRecipient]
|
|
832
|
+
})
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
return (0, import_core3.buildPartialUserOperation)({
|
|
836
|
+
sender: params.userAddress,
|
|
837
|
+
nonce: params.aaNonce,
|
|
838
|
+
operations,
|
|
839
|
+
gasLimits: {
|
|
840
|
+
callGasLimit: params.callGasLimit ?? 500000n,
|
|
841
|
+
verificationGasLimit: params.verificationGasLimit ?? 150000n,
|
|
842
|
+
preVerificationGas: params.preVerificationGas ?? 50000n
|
|
843
|
+
}
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* Build an unsigned UserOp for Scenario 2 (Burn/Redeem).
|
|
848
|
+
*
|
|
849
|
+
* Two modes:
|
|
850
|
+
* - `mode: 'burn'` — direct `PointToken.burn(amount)`; `msg.sender`
|
|
851
|
+
* via EIP-7702 delegation is the user, so no signature needed
|
|
852
|
+
* on-chain (the BurnConsent was already verified off-chain by
|
|
853
|
+
* the issuer backend before we got here)
|
|
854
|
+
* - `mode: 'burnWithSig'` — `PointToken.burnWithSig(consent, sig)`;
|
|
855
|
+
* used when the issuer hasn't verified the consent and the
|
|
856
|
+
* contract has to do it on-chain
|
|
857
|
+
*/
|
|
858
|
+
prepareBurn(params) {
|
|
859
|
+
if (!params.pointTokenAddress) {
|
|
860
|
+
throw new RelayError("ENCODE_FAILED", "prepareBurn: pointTokenAddress required");
|
|
861
|
+
}
|
|
862
|
+
if (!params.batchExecutorAddress) {
|
|
863
|
+
throw new RelayError(
|
|
864
|
+
"ENCODE_FAILED",
|
|
865
|
+
"prepareBurn: batchExecutorAddress required"
|
|
866
|
+
);
|
|
867
|
+
}
|
|
868
|
+
let burnCallData;
|
|
869
|
+
try {
|
|
870
|
+
if (params.mode === "burnWithSig") {
|
|
871
|
+
if (!params.burnConsent || !params.consentSignature) {
|
|
872
|
+
throw new Error("burnWithSig requires burnConsent + consentSignature");
|
|
873
|
+
}
|
|
874
|
+
burnCallData = (0, import_viem5.encodeFunctionData)({
|
|
875
|
+
abi: import_core3.POINT_TOKEN_V2_ABI,
|
|
876
|
+
functionName: "burnWithSig",
|
|
877
|
+
args: [params.burnConsent, params.consentSignature]
|
|
878
|
+
});
|
|
879
|
+
} else {
|
|
880
|
+
burnCallData = (0, import_viem5.encodeFunctionData)({
|
|
881
|
+
abi: import_core3.POINT_TOKEN_V2_ABI,
|
|
882
|
+
functionName: "burn",
|
|
883
|
+
args: [params.amount]
|
|
884
|
+
});
|
|
885
|
+
}
|
|
886
|
+
} catch (err) {
|
|
887
|
+
throw new RelayError(
|
|
888
|
+
"ENCODE_FAILED",
|
|
889
|
+
`prepareBurn: failed to encode burn call: ${errorMessage(err)}`,
|
|
890
|
+
err
|
|
891
|
+
);
|
|
892
|
+
}
|
|
893
|
+
const operations = [
|
|
894
|
+
{
|
|
895
|
+
target: params.pointTokenAddress,
|
|
896
|
+
value: 0n,
|
|
897
|
+
data: burnCallData
|
|
898
|
+
}
|
|
899
|
+
];
|
|
900
|
+
return (0, import_core3.buildPartialUserOperation)({
|
|
901
|
+
sender: params.userAddress,
|
|
902
|
+
nonce: params.aaNonce,
|
|
903
|
+
operations,
|
|
904
|
+
gasLimits: {
|
|
905
|
+
callGasLimit: params.callGasLimit ?? 300000n,
|
|
906
|
+
verificationGasLimit: params.verificationGasLimit ?? 150000n,
|
|
907
|
+
preVerificationGas: params.preVerificationGas ?? 50000n
|
|
908
|
+
}
|
|
909
|
+
});
|
|
910
|
+
}
|
|
758
911
|
};
|
|
759
912
|
function errorMessage(err) {
|
|
760
913
|
return err instanceof Error ? err.message : String(err);
|
|
@@ -1055,8 +1208,8 @@ var InMemoryCursorStore = class {
|
|
|
1055
1208
|
};
|
|
1056
1209
|
|
|
1057
1210
|
// src/indexer/pointIndexer.ts
|
|
1058
|
-
var
|
|
1059
|
-
var TRANSFER_EVENT = (0,
|
|
1211
|
+
var import_viem6 = require("viem");
|
|
1212
|
+
var TRANSFER_EVENT = (0, import_viem6.parseAbiItem)(
|
|
1060
1213
|
"event Transfer(address indexed from, address indexed to, uint256 value)"
|
|
1061
1214
|
);
|
|
1062
1215
|
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
@@ -1176,10 +1329,10 @@ var PointIndexer = class {
|
|
|
1176
1329
|
for (const log of logs) {
|
|
1177
1330
|
const args = log.args;
|
|
1178
1331
|
if (!args.from || !args.to || args.value === void 0) continue;
|
|
1179
|
-
if ((0,
|
|
1332
|
+
if ((0, import_viem6.getAddress)(args.from) !== ZERO_ADDRESS) continue;
|
|
1180
1333
|
if (log.blockNumber === null || log.transactionHash === null) continue;
|
|
1181
1334
|
out.push({
|
|
1182
|
-
to: (0,
|
|
1335
|
+
to: (0, import_viem6.getAddress)(args.to),
|
|
1183
1336
|
amount: args.value,
|
|
1184
1337
|
blockNumber: log.blockNumber,
|
|
1185
1338
|
txHash: log.transactionHash,
|
|
@@ -1235,8 +1388,8 @@ function pickMatchingLock(locks, amount) {
|
|
|
1235
1388
|
}
|
|
1236
1389
|
|
|
1237
1390
|
// src/indexer/burnIndexer.ts
|
|
1238
|
-
var
|
|
1239
|
-
var TRANSFER_EVENT2 = (0,
|
|
1391
|
+
var import_viem7 = require("viem");
|
|
1392
|
+
var TRANSFER_EVENT2 = (0, import_viem7.parseAbiItem)(
|
|
1240
1393
|
"event Transfer(address indexed from, address indexed to, uint256 value)"
|
|
1241
1394
|
);
|
|
1242
1395
|
var ZERO_ADDRESS2 = "0x0000000000000000000000000000000000000000";
|
|
@@ -1355,10 +1508,10 @@ var BurnIndexer = class {
|
|
|
1355
1508
|
for (const log of logs) {
|
|
1356
1509
|
const args = log.args;
|
|
1357
1510
|
if (!args.from || !args.to || args.value === void 0) continue;
|
|
1358
|
-
if ((0,
|
|
1511
|
+
if ((0, import_viem7.getAddress)(args.to) !== ZERO_ADDRESS2) continue;
|
|
1359
1512
|
if (log.blockNumber === null || log.transactionHash === null) continue;
|
|
1360
1513
|
out.push({
|
|
1361
|
-
from: (0,
|
|
1514
|
+
from: (0, import_viem7.getAddress)(args.from),
|
|
1362
1515
|
amount: args.value,
|
|
1363
1516
|
blockNumber: log.blockNumber,
|
|
1364
1517
|
txHash: log.transactionHash,
|
|
@@ -1386,7 +1539,7 @@ var BurnIndexer = class {
|
|
|
1386
1539
|
};
|
|
1387
1540
|
|
|
1388
1541
|
// src/api/handlers.ts
|
|
1389
|
-
var
|
|
1542
|
+
var import_viem8 = require("viem");
|
|
1390
1543
|
var import_core5 = require("@pafi-dev/core");
|
|
1391
1544
|
var IssuerApiHandlers = class {
|
|
1392
1545
|
authService;
|
|
@@ -1418,7 +1571,7 @@ var IssuerApiHandlers = class {
|
|
|
1418
1571
|
"IssuerApiHandlers: pointTokenAddress or pointTokenAddresses required"
|
|
1419
1572
|
);
|
|
1420
1573
|
}
|
|
1421
|
-
const normalized = raw.map((a) => (0,
|
|
1574
|
+
const normalized = raw.map((a) => (0, import_viem8.getAddress)(a));
|
|
1422
1575
|
this.supportedTokens = new Set(normalized);
|
|
1423
1576
|
this.defaultToken = normalized[0];
|
|
1424
1577
|
this.chainId = config.chainId;
|
|
@@ -1519,14 +1672,14 @@ var IssuerApiHandlers = class {
|
|
|
1519
1672
|
`handleUser: unsupported chainId ${request.chainId}`
|
|
1520
1673
|
);
|
|
1521
1674
|
}
|
|
1522
|
-
const normalizedAuthed = (0,
|
|
1523
|
-
const normalizedRequest = (0,
|
|
1675
|
+
const normalizedAuthed = (0, import_viem8.getAddress)(userAddress);
|
|
1676
|
+
const normalizedRequest = (0, import_viem8.getAddress)(request.userAddress);
|
|
1524
1677
|
if (normalizedAuthed !== normalizedRequest) {
|
|
1525
1678
|
throw new Error(
|
|
1526
1679
|
"handleUser: request userAddress must match authenticated user"
|
|
1527
1680
|
);
|
|
1528
1681
|
}
|
|
1529
|
-
const pointToken = (0,
|
|
1682
|
+
const pointToken = (0, import_viem8.getAddress)(request.pointTokenAddress);
|
|
1530
1683
|
if (!this.supportedTokens.has(pointToken)) {
|
|
1531
1684
|
throw new Error(
|
|
1532
1685
|
`handleUser: unsupported pointToken ${pointToken}`
|
|
@@ -1569,7 +1722,7 @@ var IssuerApiHandlers = class {
|
|
|
1569
1722
|
`handleBuildConsentTypedData: unsupported chainId ${request.chainId}`
|
|
1570
1723
|
);
|
|
1571
1724
|
}
|
|
1572
|
-
const pointToken = (0,
|
|
1725
|
+
const pointToken = (0, import_viem8.getAddress)(request.pointTokenAddress);
|
|
1573
1726
|
if (!this.supportedTokens.has(pointToken)) {
|
|
1574
1727
|
throw new Error(
|
|
1575
1728
|
`handleBuildConsentTypedData: unsupported pointToken ${pointToken}`
|
|
@@ -1609,14 +1762,14 @@ var IssuerApiHandlers = class {
|
|
|
1609
1762
|
`handleClaimAndSwap: unsupported chainId ${request.chainId}`
|
|
1610
1763
|
);
|
|
1611
1764
|
}
|
|
1612
|
-
const pointToken = (0,
|
|
1765
|
+
const pointToken = (0, import_viem8.getAddress)(request.pointTokenAddress);
|
|
1613
1766
|
if (!this.supportedTokens.has(pointToken)) {
|
|
1614
1767
|
throw new Error(
|
|
1615
1768
|
`handleClaimAndSwap: unsupported pointToken ${pointToken}`
|
|
1616
1769
|
);
|
|
1617
1770
|
}
|
|
1618
1771
|
const result = await this.gateway.processMintAndCashOut({
|
|
1619
|
-
userAddress: (0,
|
|
1772
|
+
userAddress: (0, import_viem8.getAddress)(userAddress),
|
|
1620
1773
|
pointTokenAddress: pointToken,
|
|
1621
1774
|
chainId: request.chainId,
|
|
1622
1775
|
domain: request.domain,
|
|
@@ -1636,6 +1789,183 @@ var IssuerApiHandlers = class {
|
|
|
1636
1789
|
}
|
|
1637
1790
|
};
|
|
1638
1791
|
|
|
1792
|
+
// src/api/handlers/ptRedeemHandler.ts
|
|
1793
|
+
var import_viem9 = require("viem");
|
|
1794
|
+
var import_core6 = require("@pafi-dev/core");
|
|
1795
|
+
var DEFAULT_REDEEM_LOCK_MS = 15 * 60 * 1e3;
|
|
1796
|
+
var PTRedeemError = class extends Error {
|
|
1797
|
+
constructor(code, message) {
|
|
1798
|
+
super(message);
|
|
1799
|
+
this.code = code;
|
|
1800
|
+
this.name = "PTRedeemError";
|
|
1801
|
+
}
|
|
1802
|
+
code;
|
|
1803
|
+
};
|
|
1804
|
+
var PTRedeemHandler = class {
|
|
1805
|
+
ledger;
|
|
1806
|
+
relayService;
|
|
1807
|
+
pointTokenAddress;
|
|
1808
|
+
batchExecutorAddress;
|
|
1809
|
+
chainId;
|
|
1810
|
+
domain;
|
|
1811
|
+
redeemLockDurationMs;
|
|
1812
|
+
now;
|
|
1813
|
+
constructor(config) {
|
|
1814
|
+
if (!config.ledger.reservePendingCredit) {
|
|
1815
|
+
throw new PTRedeemError(
|
|
1816
|
+
"LEDGER_NOT_SUPPORTED",
|
|
1817
|
+
"PTRedeemHandler requires a ledger that implements reservePendingCredit() (v0.3.0+)"
|
|
1818
|
+
);
|
|
1819
|
+
}
|
|
1820
|
+
this.ledger = config.ledger;
|
|
1821
|
+
this.relayService = config.relayService;
|
|
1822
|
+
this.pointTokenAddress = (0, import_viem9.getAddress)(config.pointTokenAddress);
|
|
1823
|
+
this.batchExecutorAddress = (0, import_viem9.getAddress)(config.batchExecutorAddress);
|
|
1824
|
+
this.chainId = config.chainId;
|
|
1825
|
+
this.domain = config.domain;
|
|
1826
|
+
this.redeemLockDurationMs = config.redeemLockDurationMs ?? DEFAULT_REDEEM_LOCK_MS;
|
|
1827
|
+
this.now = config.now ?? (() => Date.now());
|
|
1828
|
+
}
|
|
1829
|
+
async handle(request) {
|
|
1830
|
+
if (request.amount <= 0n) {
|
|
1831
|
+
throw new PTRedeemError("INVALID_CONSENT", "redeem amount must be positive");
|
|
1832
|
+
}
|
|
1833
|
+
if (request.consent.amount !== request.amount) {
|
|
1834
|
+
throw new PTRedeemError(
|
|
1835
|
+
"AMOUNT_MISMATCH",
|
|
1836
|
+
`consent.amount (${request.consent.amount}) must match request.amount (${request.amount})`
|
|
1837
|
+
);
|
|
1838
|
+
}
|
|
1839
|
+
const nowSeconds = BigInt(Math.floor(this.now() / 1e3));
|
|
1840
|
+
if (request.consent.deadline <= nowSeconds) {
|
|
1841
|
+
throw new PTRedeemError(
|
|
1842
|
+
"EXPIRED_CONSENT",
|
|
1843
|
+
`consent deadline (${request.consent.deadline}) already passed`
|
|
1844
|
+
);
|
|
1845
|
+
}
|
|
1846
|
+
const verification = await (0, import_core6.verifyBurnConsent)(
|
|
1847
|
+
{
|
|
1848
|
+
name: this.domain.name,
|
|
1849
|
+
chainId: this.chainId,
|
|
1850
|
+
verifyingContract: this.domain.verifyingContract ?? this.pointTokenAddress
|
|
1851
|
+
},
|
|
1852
|
+
request.consent,
|
|
1853
|
+
request.consentSignature,
|
|
1854
|
+
request.userAddress
|
|
1855
|
+
);
|
|
1856
|
+
if (!verification.isValid) {
|
|
1857
|
+
throw new PTRedeemError(
|
|
1858
|
+
"SIGNATURE_MISMATCH",
|
|
1859
|
+
`signer mismatch \u2014 expected ${request.userAddress}, got ${verification.recoveredAddress}`
|
|
1860
|
+
);
|
|
1861
|
+
}
|
|
1862
|
+
const lockId = await this.ledger.reservePendingCredit(
|
|
1863
|
+
request.userAddress,
|
|
1864
|
+
request.amount,
|
|
1865
|
+
this.redeemLockDurationMs,
|
|
1866
|
+
this.pointTokenAddress
|
|
1867
|
+
);
|
|
1868
|
+
const userOp = this.relayService.prepareBurn({
|
|
1869
|
+
mode: "burnWithSig",
|
|
1870
|
+
userAddress: request.userAddress,
|
|
1871
|
+
aaNonce: request.aaNonce,
|
|
1872
|
+
pointTokenAddress: this.pointTokenAddress,
|
|
1873
|
+
batchExecutorAddress: this.batchExecutorAddress,
|
|
1874
|
+
burnConsent: request.consent,
|
|
1875
|
+
consentSignature: parseSigStruct(request.consentSignature)
|
|
1876
|
+
});
|
|
1877
|
+
return {
|
|
1878
|
+
lockId,
|
|
1879
|
+
userOp,
|
|
1880
|
+
expiresInSeconds: Math.floor(this.redeemLockDurationMs / 1e3)
|
|
1881
|
+
};
|
|
1882
|
+
}
|
|
1883
|
+
};
|
|
1884
|
+
function parseSigStruct(serialized) {
|
|
1885
|
+
const raw = serialized.slice(2);
|
|
1886
|
+
if (raw.length !== 130) {
|
|
1887
|
+
throw new PTRedeemError(
|
|
1888
|
+
"INVALID_CONSENT",
|
|
1889
|
+
`signature must be 65 bytes, got ${raw.length / 2}`
|
|
1890
|
+
);
|
|
1891
|
+
}
|
|
1892
|
+
const r = `0x${raw.slice(0, 64)}`;
|
|
1893
|
+
const s = `0x${raw.slice(64, 128)}`;
|
|
1894
|
+
const v = parseInt(raw.slice(128, 130), 16);
|
|
1895
|
+
return { v, r, s };
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
// src/api/handlers/topUpRedemptionHandler.ts
|
|
1899
|
+
var import_viem10 = require("viem");
|
|
1900
|
+
var import_core7 = require("@pafi-dev/core");
|
|
1901
|
+
var TopUpRedemptionError = class extends Error {
|
|
1902
|
+
constructor(code, message) {
|
|
1903
|
+
super(message);
|
|
1904
|
+
this.code = code;
|
|
1905
|
+
this.name = "TopUpRedemptionError";
|
|
1906
|
+
}
|
|
1907
|
+
code;
|
|
1908
|
+
};
|
|
1909
|
+
var TopUpRedemptionHandler = class {
|
|
1910
|
+
ledger;
|
|
1911
|
+
ptRedeemHandler;
|
|
1912
|
+
provider;
|
|
1913
|
+
pointTokenAddress;
|
|
1914
|
+
constructor(config) {
|
|
1915
|
+
this.ledger = config.ledger;
|
|
1916
|
+
this.ptRedeemHandler = config.ptRedeemHandler;
|
|
1917
|
+
this.provider = config.provider;
|
|
1918
|
+
this.pointTokenAddress = (0, import_viem10.getAddress)(config.pointTokenAddress);
|
|
1919
|
+
}
|
|
1920
|
+
async handle(request) {
|
|
1921
|
+
const offChainBalance = await this.ledger.getBalance(
|
|
1922
|
+
request.userAddress,
|
|
1923
|
+
this.pointTokenAddress
|
|
1924
|
+
);
|
|
1925
|
+
if (offChainBalance >= request.requiredAmount) {
|
|
1926
|
+
return { action: "NO_TOP_UP_NEEDED", offChainBalance };
|
|
1927
|
+
}
|
|
1928
|
+
const shortfall = request.requiredAmount - offChainBalance;
|
|
1929
|
+
const onChainBalance = await (0, import_core7.getPointTokenBalance)(
|
|
1930
|
+
this.provider,
|
|
1931
|
+
this.pointTokenAddress,
|
|
1932
|
+
request.userAddress
|
|
1933
|
+
);
|
|
1934
|
+
if (onChainBalance < shortfall) {
|
|
1935
|
+
return {
|
|
1936
|
+
action: "INSUFFICIENT_ONCHAIN",
|
|
1937
|
+
offChainBalance,
|
|
1938
|
+
onChainBalance,
|
|
1939
|
+
shortfall
|
|
1940
|
+
};
|
|
1941
|
+
}
|
|
1942
|
+
if (request.redeemRequest.consent.amount < shortfall) {
|
|
1943
|
+
throw new TopUpRedemptionError(
|
|
1944
|
+
"CONSENT_AMOUNT_TOO_LOW",
|
|
1945
|
+
`consent.amount (${request.redeemRequest.consent.amount}) must cover shortfall (${shortfall})`
|
|
1946
|
+
);
|
|
1947
|
+
}
|
|
1948
|
+
if (request.redeemRequest.consent.amount !== shortfall) {
|
|
1949
|
+
throw new TopUpRedemptionError(
|
|
1950
|
+
"CONSENT_AMOUNT_TOO_LOW",
|
|
1951
|
+
`consent.amount (${request.redeemRequest.consent.amount}) must equal shortfall (${shortfall}) exactly \u2014 re-sign with correct amount`
|
|
1952
|
+
);
|
|
1953
|
+
}
|
|
1954
|
+
const redeem = await this.ptRedeemHandler.handle({
|
|
1955
|
+
userAddress: request.userAddress,
|
|
1956
|
+
amount: shortfall,
|
|
1957
|
+
consent: request.redeemRequest.consent,
|
|
1958
|
+
consentSignature: request.redeemRequest.consentSignature,
|
|
1959
|
+
aaNonce: request.redeemRequest.aaNonce
|
|
1960
|
+
});
|
|
1961
|
+
return {
|
|
1962
|
+
action: "TOP_UP_STARTED",
|
|
1963
|
+
shortfall,
|
|
1964
|
+
redeem
|
|
1965
|
+
};
|
|
1966
|
+
}
|
|
1967
|
+
};
|
|
1968
|
+
|
|
1639
1969
|
// src/pools/subgraphPoolsProvider.ts
|
|
1640
1970
|
var DEFAULT_CACHE_TTL_MS = 3e4;
|
|
1641
1971
|
var POOL_QUERY = `
|
|
@@ -1848,7 +2178,7 @@ function toUsdtPerNative(priceFloat, usdtDecimals) {
|
|
|
1848
2178
|
}
|
|
1849
2179
|
|
|
1850
2180
|
// src/balance/balanceAggregator.ts
|
|
1851
|
-
var
|
|
2181
|
+
var import_core8 = require("@pafi-dev/core");
|
|
1852
2182
|
var BalanceAggregator = class {
|
|
1853
2183
|
provider;
|
|
1854
2184
|
ledger;
|
|
@@ -1869,7 +2199,7 @@ var BalanceAggregator = class {
|
|
|
1869
2199
|
async getCombinedBalance(user, pointToken) {
|
|
1870
2200
|
const [offChain, onChain] = await Promise.all([
|
|
1871
2201
|
this.ledger.getBalance(user, pointToken),
|
|
1872
|
-
(0,
|
|
2202
|
+
(0, import_core8.getPointTokenBalance)(this.provider, pointToken, user)
|
|
1873
2203
|
]);
|
|
1874
2204
|
return {
|
|
1875
2205
|
offChain,
|
|
@@ -2114,7 +2444,7 @@ var PafiBackendClient = class {
|
|
|
2114
2444
|
};
|
|
2115
2445
|
|
|
2116
2446
|
// src/config.ts
|
|
2117
|
-
var
|
|
2447
|
+
var import_viem11 = require("viem");
|
|
2118
2448
|
function createIssuerService(config) {
|
|
2119
2449
|
if (!config.provider) {
|
|
2120
2450
|
throw new Error("createIssuerService: provider is required");
|
|
@@ -2140,7 +2470,7 @@ function createIssuerService(config) {
|
|
|
2140
2470
|
"createIssuerService: at least one of pointTokenAddress / pointTokenAddresses is required"
|
|
2141
2471
|
);
|
|
2142
2472
|
}
|
|
2143
|
-
const tokenAddresses = rawAddresses.map((a) => (0,
|
|
2473
|
+
const tokenAddresses = rawAddresses.map((a) => (0, import_viem11.getAddress)(a));
|
|
2144
2474
|
const ledger = config.ledger ?? new MemoryPointLedger();
|
|
2145
2475
|
const sessionStore = config.sessionStore ?? new MemorySessionStore();
|
|
2146
2476
|
const policy = config.policy ?? new DefaultPolicyEngine({ ledger });
|
|
@@ -2258,12 +2588,16 @@ var PAFI_ISSUER_SDK_VERSION = "0.1.0";
|
|
|
2258
2588
|
MintingGatewayError,
|
|
2259
2589
|
NonceManager,
|
|
2260
2590
|
PAFI_ISSUER_SDK_VERSION,
|
|
2591
|
+
PTRedeemError,
|
|
2592
|
+
PTRedeemHandler,
|
|
2261
2593
|
PafiBackendClient,
|
|
2262
2594
|
PafiBackendError,
|
|
2263
2595
|
PointIndexer,
|
|
2264
2596
|
PrivateKeySigner,
|
|
2265
2597
|
RelayError,
|
|
2266
2598
|
RelayService,
|
|
2599
|
+
TopUpRedemptionError,
|
|
2600
|
+
TopUpRedemptionHandler,
|
|
2267
2601
|
authenticateRequest,
|
|
2268
2602
|
createIssuerService,
|
|
2269
2603
|
createSubgraphNativeUsdtQuoter,
|