@pafi-dev/issuer 0.5.33 → 0.5.35
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 +706 -174
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +923 -516
- package/dist/index.d.ts +923 -516
- package/dist/index.js +702 -162
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -23,6 +23,8 @@ __export(index_exports, {
|
|
|
23
23
|
AuthError: () => AuthError,
|
|
24
24
|
AuthService: () => AuthService,
|
|
25
25
|
BalanceAggregator: () => BalanceAggregator,
|
|
26
|
+
BundlerNotConfiguredError: () => BundlerNotConfiguredError,
|
|
27
|
+
BundlerRejectedError: () => BundlerRejectedError,
|
|
26
28
|
BurnIndexer: () => BurnIndexer,
|
|
27
29
|
DefaultPolicyEngine: () => DefaultPolicyEngine,
|
|
28
30
|
FeeManager: () => FeeManager,
|
|
@@ -34,14 +36,21 @@ __export(index_exports, {
|
|
|
34
36
|
MemorySessionStore: () => MemorySessionStore,
|
|
35
37
|
NonceManager: () => NonceManager,
|
|
36
38
|
PAFI_ISSUER_SDK_VERSION: () => PAFI_ISSUER_SDK_VERSION,
|
|
37
|
-
PAFI_SUBGRAPH_URL: () =>
|
|
39
|
+
PAFI_SUBGRAPH_URL: () => import_core12.PAFI_SUBGRAPH_URL,
|
|
40
|
+
PTClaimError: () => PTClaimError,
|
|
41
|
+
PTClaimHandler: () => PTClaimHandler,
|
|
38
42
|
PTRedeemError: () => PTRedeemError,
|
|
39
43
|
PTRedeemHandler: () => PTRedeemHandler,
|
|
40
44
|
PafiBackendClient: () => PafiBackendClient,
|
|
41
45
|
PafiBackendError: () => PafiBackendError,
|
|
46
|
+
PendingUserOpNotFoundError: () => PendingUserOpNotFoundError,
|
|
47
|
+
PerpDepositError: () => PerpDepositError,
|
|
48
|
+
PerpDepositHandler: () => PerpDepositHandler,
|
|
42
49
|
PointIndexer: () => PointIndexer,
|
|
43
50
|
RelayError: () => RelayError,
|
|
44
51
|
RelayService: () => RelayService,
|
|
52
|
+
SwapError: () => SwapError,
|
|
53
|
+
SwapHandler: () => SwapHandler,
|
|
45
54
|
TopUpRedemptionError: () => TopUpRedemptionError,
|
|
46
55
|
TopUpRedemptionHandler: () => TopUpRedemptionHandler,
|
|
47
56
|
authenticateRequest: () => authenticateRequest,
|
|
@@ -50,9 +59,13 @@ __export(index_exports, {
|
|
|
50
59
|
createSubgraphNativeUsdtQuoter: () => createSubgraphNativeUsdtQuoter,
|
|
51
60
|
createSubgraphPoolsProvider: () => createSubgraphPoolsProvider,
|
|
52
61
|
handleClaimStatus: () => handleClaimStatus,
|
|
62
|
+
handleMobilePrepare: () => handleMobilePrepare,
|
|
63
|
+
handleMobileSubmit: () => handleMobileSubmit,
|
|
53
64
|
handleRedeemStatus: () => handleRedeemStatus,
|
|
54
65
|
mergePaymasterFields: () => mergePaymasterFields,
|
|
55
66
|
prepareMobileUserOp: () => prepareMobileUserOp,
|
|
67
|
+
relayUserOp: () => relayUserOp,
|
|
68
|
+
requestPaymaster: () => requestPaymaster,
|
|
56
69
|
serializeEntryToJsonRpc: () => serializeEntryToJsonRpc,
|
|
57
70
|
serializeUserOpTypedData: () => serializeUserOpTypedData
|
|
58
71
|
});
|
|
@@ -1743,9 +1756,662 @@ async function handleRedeemStatus(params) {
|
|
|
1743
1756
|
};
|
|
1744
1757
|
}
|
|
1745
1758
|
|
|
1746
|
-
// src/
|
|
1747
|
-
var
|
|
1759
|
+
// src/api/mobileHandlers.ts
|
|
1760
|
+
var import_core8 = require("@pafi-dev/core");
|
|
1761
|
+
|
|
1762
|
+
// src/userop-store/serialize.ts
|
|
1748
1763
|
var import_core6 = require("@pafi-dev/core");
|
|
1764
|
+
function serializeEntryToJsonRpc(entry, signature, variant = "sponsored") {
|
|
1765
|
+
if (variant === "fallback") {
|
|
1766
|
+
if (!entry.fallback) {
|
|
1767
|
+
throw new Error(
|
|
1768
|
+
"serializeEntryToJsonRpc: variant=fallback requested but the stored entry has no `fallback` branch \u2014 caller should resubmit with variant='sponsored' or re-prepare with a fee configured."
|
|
1769
|
+
);
|
|
1770
|
+
}
|
|
1771
|
+
return (0, import_core6.serializeUserOpToJsonRpc)(
|
|
1772
|
+
{
|
|
1773
|
+
sender: entry.sender,
|
|
1774
|
+
nonce: BigInt(entry.nonce),
|
|
1775
|
+
callData: entry.fallback.callData,
|
|
1776
|
+
callGasLimit: BigInt(entry.fallback.callGasLimit),
|
|
1777
|
+
verificationGasLimit: BigInt(entry.fallback.verificationGasLimit),
|
|
1778
|
+
preVerificationGas: BigInt(entry.fallback.preVerificationGas),
|
|
1779
|
+
maxFeePerGas: BigInt(entry.maxFeePerGas),
|
|
1780
|
+
maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas)
|
|
1781
|
+
// intentionally no paymaster — user pays ETH gas
|
|
1782
|
+
},
|
|
1783
|
+
signature
|
|
1784
|
+
);
|
|
1785
|
+
}
|
|
1786
|
+
return (0, import_core6.serializeUserOpToJsonRpc)(
|
|
1787
|
+
{
|
|
1788
|
+
sender: entry.sender,
|
|
1789
|
+
nonce: BigInt(entry.nonce),
|
|
1790
|
+
callData: entry.callData,
|
|
1791
|
+
callGasLimit: BigInt(entry.callGasLimit),
|
|
1792
|
+
verificationGasLimit: BigInt(entry.verificationGasLimit),
|
|
1793
|
+
preVerificationGas: BigInt(entry.preVerificationGas),
|
|
1794
|
+
maxFeePerGas: BigInt(entry.maxFeePerGas),
|
|
1795
|
+
maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas),
|
|
1796
|
+
paymaster: entry.paymaster,
|
|
1797
|
+
paymasterVerificationGasLimit: entry.paymasterVerificationGasLimit != null ? BigInt(entry.paymasterVerificationGasLimit) : void 0,
|
|
1798
|
+
paymasterPostOpGasLimit: entry.paymasterPostOpGasLimit != null ? BigInt(entry.paymasterPostOpGasLimit) : void 0,
|
|
1799
|
+
paymasterData: entry.paymasterData
|
|
1800
|
+
},
|
|
1801
|
+
signature
|
|
1802
|
+
);
|
|
1803
|
+
}
|
|
1804
|
+
|
|
1805
|
+
// src/userop-store/prepareUserOp.ts
|
|
1806
|
+
var import_core7 = require("@pafi-dev/core");
|
|
1807
|
+
function serializeUserOpTypedData(td) {
|
|
1808
|
+
return {
|
|
1809
|
+
domain: td.domain,
|
|
1810
|
+
types: td.types,
|
|
1811
|
+
primaryType: td.primaryType,
|
|
1812
|
+
message: {
|
|
1813
|
+
sender: td.message.sender,
|
|
1814
|
+
nonce: `0x${td.message.nonce.toString(16)}`,
|
|
1815
|
+
initCode: td.message.initCode,
|
|
1816
|
+
callData: td.message.callData,
|
|
1817
|
+
accountGasLimits: td.message.accountGasLimits,
|
|
1818
|
+
preVerificationGas: `0x${td.message.preVerificationGas.toString(
|
|
1819
|
+
16
|
|
1820
|
+
)}`,
|
|
1821
|
+
gasFees: td.message.gasFees,
|
|
1822
|
+
paymasterAndData: td.message.paymasterAndData
|
|
1823
|
+
}
|
|
1824
|
+
};
|
|
1825
|
+
}
|
|
1826
|
+
function mergePaymasterFields(userOp, paymasterFields) {
|
|
1827
|
+
if (!paymasterFields) return userOp;
|
|
1828
|
+
const merged = {
|
|
1829
|
+
...userOp
|
|
1830
|
+
};
|
|
1831
|
+
for (const [k, v] of Object.entries(paymasterFields)) {
|
|
1832
|
+
if (v !== void 0) merged[k] = v;
|
|
1833
|
+
}
|
|
1834
|
+
return merged;
|
|
1835
|
+
}
|
|
1836
|
+
async function prepareMobileUserOp(params) {
|
|
1837
|
+
const userOp = mergePaymasterFields(
|
|
1838
|
+
params.partialUserOp,
|
|
1839
|
+
params.paymasterFields
|
|
1840
|
+
);
|
|
1841
|
+
const userOpHash = (0, import_core7.computeUserOpHash)(userOp, params.chainId);
|
|
1842
|
+
const typedData = serializeUserOpTypedData(
|
|
1843
|
+
(0, import_core7.buildUserOpTypedData)(userOp, params.chainId)
|
|
1844
|
+
);
|
|
1845
|
+
let fallback;
|
|
1846
|
+
let fallbackEntry;
|
|
1847
|
+
if (params.partialUserOpFallback) {
|
|
1848
|
+
const fallbackUserOp = {
|
|
1849
|
+
...params.partialUserOpFallback,
|
|
1850
|
+
maxFeePerGas: userOp.maxFeePerGas,
|
|
1851
|
+
maxPriorityFeePerGas: userOp.maxPriorityFeePerGas
|
|
1852
|
+
};
|
|
1853
|
+
const fallbackHash = (0, import_core7.computeUserOpHash)(fallbackUserOp, params.chainId);
|
|
1854
|
+
const fallbackTypedData = serializeUserOpTypedData(
|
|
1855
|
+
(0, import_core7.buildUserOpTypedData)(fallbackUserOp, params.chainId)
|
|
1856
|
+
);
|
|
1857
|
+
fallback = {
|
|
1858
|
+
userOp: fallbackUserOp,
|
|
1859
|
+
userOpHash: fallbackHash,
|
|
1860
|
+
typedData: fallbackTypedData
|
|
1861
|
+
};
|
|
1862
|
+
fallbackEntry = {
|
|
1863
|
+
callData: fallbackUserOp.callData,
|
|
1864
|
+
callGasLimit: fallbackUserOp.callGasLimit.toString(),
|
|
1865
|
+
verificationGasLimit: fallbackUserOp.verificationGasLimit.toString(),
|
|
1866
|
+
preVerificationGas: fallbackUserOp.preVerificationGas.toString(),
|
|
1867
|
+
userOpHash: fallbackHash
|
|
1868
|
+
};
|
|
1869
|
+
}
|
|
1870
|
+
const entry = {
|
|
1871
|
+
sender: userOp.sender,
|
|
1872
|
+
nonce: userOp.nonce.toString(),
|
|
1873
|
+
callData: userOp.callData,
|
|
1874
|
+
callGasLimit: userOp.callGasLimit.toString(),
|
|
1875
|
+
verificationGasLimit: userOp.verificationGasLimit.toString(),
|
|
1876
|
+
preVerificationGas: userOp.preVerificationGas.toString(),
|
|
1877
|
+
maxFeePerGas: userOp.maxFeePerGas.toString(),
|
|
1878
|
+
maxPriorityFeePerGas: userOp.maxPriorityFeePerGas.toString(),
|
|
1879
|
+
paymaster: userOp.paymaster,
|
|
1880
|
+
paymasterVerificationGasLimit: userOp.paymasterVerificationGasLimit?.toString(),
|
|
1881
|
+
paymasterPostOpGasLimit: userOp.paymasterPostOpGasLimit?.toString(),
|
|
1882
|
+
paymasterData: userOp.paymasterData,
|
|
1883
|
+
chainId: params.chainId,
|
|
1884
|
+
userOpHash,
|
|
1885
|
+
fallback: fallbackEntry
|
|
1886
|
+
};
|
|
1887
|
+
await params.store.save(params.lockId, entry, params.ttlSeconds);
|
|
1888
|
+
return {
|
|
1889
|
+
sponsored: { userOp, userOpHash, typedData },
|
|
1890
|
+
fallback,
|
|
1891
|
+
entry
|
|
1892
|
+
};
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
// src/pafi-backend/helpers.ts
|
|
1896
|
+
var BundlerNotConfiguredError = class extends Error {
|
|
1897
|
+
code = "BUNDLER_NOT_CONFIGURED";
|
|
1898
|
+
constructor() {
|
|
1899
|
+
super(
|
|
1900
|
+
"PAFI backend client not configured \u2014 set PAFI_BACKEND_URL, PAFI_ISSUER_ID, PAFI_API_KEY to enable mobile submit."
|
|
1901
|
+
);
|
|
1902
|
+
this.name = "BundlerNotConfiguredError";
|
|
1903
|
+
}
|
|
1904
|
+
};
|
|
1905
|
+
var BundlerRejectedError = class extends Error {
|
|
1906
|
+
code = "BUNDLER_REJECTED";
|
|
1907
|
+
cause;
|
|
1908
|
+
constructor(message, cause) {
|
|
1909
|
+
super(message);
|
|
1910
|
+
this.name = "BundlerRejectedError";
|
|
1911
|
+
this.cause = cause;
|
|
1912
|
+
}
|
|
1913
|
+
};
|
|
1914
|
+
async function requestPaymaster(params) {
|
|
1915
|
+
if (!params.client) return void 0;
|
|
1916
|
+
const fn = params.functionName ?? defaultFunctionForScenario(params.scenario);
|
|
1917
|
+
try {
|
|
1918
|
+
return await params.client.requestSponsorship({
|
|
1919
|
+
chainId: params.chainId,
|
|
1920
|
+
scenario: params.scenario,
|
|
1921
|
+
userOp: params.userOp,
|
|
1922
|
+
target: {
|
|
1923
|
+
contract: params.pointTokenAddress,
|
|
1924
|
+
function: fn,
|
|
1925
|
+
pointToken: params.pointTokenAddress
|
|
1926
|
+
}
|
|
1927
|
+
});
|
|
1928
|
+
} catch (err) {
|
|
1929
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1930
|
+
params.onWarning?.(`Paymaster sponsorship declined: ${msg}`);
|
|
1931
|
+
return void 0;
|
|
1932
|
+
}
|
|
1933
|
+
}
|
|
1934
|
+
function defaultFunctionForScenario(scenario) {
|
|
1935
|
+
switch (scenario) {
|
|
1936
|
+
case "mint":
|
|
1937
|
+
return "mint";
|
|
1938
|
+
case "burn":
|
|
1939
|
+
return "burn";
|
|
1940
|
+
case "swap":
|
|
1941
|
+
return "swap";
|
|
1942
|
+
case "perp-deposit":
|
|
1943
|
+
return "deposit";
|
|
1944
|
+
default:
|
|
1945
|
+
return scenario;
|
|
1946
|
+
}
|
|
1947
|
+
}
|
|
1948
|
+
async function relayUserOp(params) {
|
|
1949
|
+
if (!params.client) {
|
|
1950
|
+
throw new BundlerNotConfiguredError();
|
|
1951
|
+
}
|
|
1952
|
+
try {
|
|
1953
|
+
const result = await params.client.relayUserOperation({
|
|
1954
|
+
userOp: params.userOp,
|
|
1955
|
+
entryPoint: params.entryPoint,
|
|
1956
|
+
eip7702Auth: params.eip7702Auth
|
|
1957
|
+
});
|
|
1958
|
+
return { userOpHash: result.userOpHash };
|
|
1959
|
+
} catch (err) {
|
|
1960
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1961
|
+
throw new BundlerRejectedError(msg, err);
|
|
1962
|
+
}
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
// src/api/mobileHandlers.ts
|
|
1966
|
+
var PendingUserOpNotFoundError = class extends Error {
|
|
1967
|
+
code = "PENDING_USEROP_NOT_FOUND";
|
|
1968
|
+
constructor(lockId) {
|
|
1969
|
+
super(
|
|
1970
|
+
`No pending UserOp found for lockId ${lockId} \u2014 it may have expired or already been submitted.`
|
|
1971
|
+
);
|
|
1972
|
+
this.name = "PendingUserOpNotFoundError";
|
|
1973
|
+
}
|
|
1974
|
+
};
|
|
1975
|
+
async function handleMobilePrepare(params) {
|
|
1976
|
+
const [fees, userCode] = await Promise.all([
|
|
1977
|
+
params.provider.estimateFeesPerGas(),
|
|
1978
|
+
params.provider.getCode({ address: params.userAddress })
|
|
1979
|
+
]);
|
|
1980
|
+
const needsDelegation = (0, import_core8.parseEip7702DelegatedAddress)(userCode) === null;
|
|
1981
|
+
const sponsoredOp = {
|
|
1982
|
+
...params.partialUserOp,
|
|
1983
|
+
maxFeePerGas: fees.maxFeePerGas ?? params.partialUserOp.maxFeePerGas ?? 0n,
|
|
1984
|
+
maxPriorityFeePerGas: fees.maxPriorityFeePerGas ?? params.partialUserOp.maxPriorityFeePerGas ?? 0n
|
|
1985
|
+
};
|
|
1986
|
+
const paymasterFields = await requestPaymaster({
|
|
1987
|
+
client: params.pafiBackendClient,
|
|
1988
|
+
chainId: params.chainId,
|
|
1989
|
+
scenario: params.scenario,
|
|
1990
|
+
userOp: sponsoredOp,
|
|
1991
|
+
pointTokenAddress: params.pointTokenAddress,
|
|
1992
|
+
onWarning: params.onWarning
|
|
1993
|
+
});
|
|
1994
|
+
const prepared = await prepareMobileUserOp({
|
|
1995
|
+
lockId: params.lockId,
|
|
1996
|
+
partialUserOp: sponsoredOp,
|
|
1997
|
+
partialUserOpFallback: params.partialUserOpFallback,
|
|
1998
|
+
paymasterFields,
|
|
1999
|
+
chainId: params.chainId,
|
|
2000
|
+
store: params.store,
|
|
2001
|
+
ttlSeconds: params.ttlSeconds
|
|
2002
|
+
});
|
|
2003
|
+
return {
|
|
2004
|
+
...prepared,
|
|
2005
|
+
isSponsored: !!paymasterFields,
|
|
2006
|
+
needsDelegation
|
|
2007
|
+
};
|
|
2008
|
+
}
|
|
2009
|
+
async function handleMobileSubmit(params) {
|
|
2010
|
+
const entry = await params.store.get(params.lockId);
|
|
2011
|
+
if (!entry) {
|
|
2012
|
+
throw new PendingUserOpNotFoundError(params.lockId);
|
|
2013
|
+
}
|
|
2014
|
+
const variant = params.variant ?? "sponsored";
|
|
2015
|
+
const userOpJson = serializeEntryToJsonRpc(entry, params.signature, variant);
|
|
2016
|
+
const result = await relayUserOp({
|
|
2017
|
+
client: params.pafiBackendClient,
|
|
2018
|
+
userOp: userOpJson,
|
|
2019
|
+
entryPoint: params.entryPoint ?? import_core8.ENTRY_POINT_V08
|
|
2020
|
+
});
|
|
2021
|
+
await params.bindUserOpHash(params.lockId, result.userOpHash);
|
|
2022
|
+
await params.store.delete(params.lockId);
|
|
2023
|
+
return { userOpHash: result.userOpHash };
|
|
2024
|
+
}
|
|
2025
|
+
|
|
2026
|
+
// src/api/handlers/ptClaimHandler.ts
|
|
2027
|
+
var import_viem9 = require("viem");
|
|
2028
|
+
var import_core9 = require("@pafi-dev/core");
|
|
2029
|
+
|
|
2030
|
+
// src/issuer-state/types.ts
|
|
2031
|
+
var IssuerStateError = class extends Error {
|
|
2032
|
+
constructor(code, message, details) {
|
|
2033
|
+
super(message);
|
|
2034
|
+
this.code = code;
|
|
2035
|
+
this.details = details;
|
|
2036
|
+
this.name = "IssuerStateError";
|
|
2037
|
+
}
|
|
2038
|
+
code;
|
|
2039
|
+
details;
|
|
2040
|
+
};
|
|
2041
|
+
|
|
2042
|
+
// src/api/handlers/ptClaimHandler.ts
|
|
2043
|
+
var PTClaimError = class extends Error {
|
|
2044
|
+
constructor(code, message, details) {
|
|
2045
|
+
super(message);
|
|
2046
|
+
this.code = code;
|
|
2047
|
+
this.details = details;
|
|
2048
|
+
this.name = "PTClaimError";
|
|
2049
|
+
}
|
|
2050
|
+
code;
|
|
2051
|
+
details;
|
|
2052
|
+
};
|
|
2053
|
+
var DEFAULT_LOCK_MS = 15 * 60 * 1e3;
|
|
2054
|
+
var DEFAULT_SIG_DEADLINE_SEC2 = 15 * 60;
|
|
2055
|
+
var PTClaimHandler = class {
|
|
2056
|
+
cfg;
|
|
2057
|
+
constructor(config) {
|
|
2058
|
+
this.cfg = {
|
|
2059
|
+
...config,
|
|
2060
|
+
lockDurationMs: config.lockDurationMs ?? DEFAULT_LOCK_MS,
|
|
2061
|
+
signatureDeadlineSeconds: config.signatureDeadlineSeconds ?? DEFAULT_SIG_DEADLINE_SEC2,
|
|
2062
|
+
now: config.now ?? (() => Date.now())
|
|
2063
|
+
};
|
|
2064
|
+
}
|
|
2065
|
+
async handle(request) {
|
|
2066
|
+
if ((0, import_viem9.getAddress)(request.authenticatedAddress) !== (0, import_viem9.getAddress)(request.userAddress)) {
|
|
2067
|
+
throw new PTClaimError(
|
|
2068
|
+
"VALIDATION_FAILED",
|
|
2069
|
+
`userAddress (${request.userAddress}) does not match authenticated session (${request.authenticatedAddress})`
|
|
2070
|
+
);
|
|
2071
|
+
}
|
|
2072
|
+
if (request.amount <= 0n) {
|
|
2073
|
+
throw new PTClaimError("INVALID_AMOUNT", "claim amount must be positive");
|
|
2074
|
+
}
|
|
2075
|
+
if (this.cfg.issuerStateValidator) {
|
|
2076
|
+
try {
|
|
2077
|
+
await this.cfg.issuerStateValidator.preValidateMint(
|
|
2078
|
+
request.pointTokenAddress,
|
|
2079
|
+
request.amount
|
|
2080
|
+
);
|
|
2081
|
+
} catch (err) {
|
|
2082
|
+
if (err instanceof IssuerStateError) throw err;
|
|
2083
|
+
throw new PTClaimError(
|
|
2084
|
+
"VALIDATION_FAILED",
|
|
2085
|
+
`issuer-state pre-validate failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2086
|
+
);
|
|
2087
|
+
}
|
|
2088
|
+
}
|
|
2089
|
+
const { batchExecutor: batchExecutorAddress } = (0, import_core9.getContractAddresses)(
|
|
2090
|
+
request.chainId
|
|
2091
|
+
);
|
|
2092
|
+
const lockId = await this.cfg.ledger.lockForMinting(
|
|
2093
|
+
request.userAddress,
|
|
2094
|
+
request.amount,
|
|
2095
|
+
this.cfg.lockDurationMs,
|
|
2096
|
+
request.pointTokenAddress
|
|
2097
|
+
);
|
|
2098
|
+
const signatureDeadline = BigInt(
|
|
2099
|
+
Math.floor(this.cfg.now() / 1e3) + this.cfg.signatureDeadlineSeconds
|
|
2100
|
+
);
|
|
2101
|
+
const feeAmount = this.cfg.feeService ? await this.cfg.feeService.estimateGasFee() : 0n;
|
|
2102
|
+
const domain = {
|
|
2103
|
+
name: this.cfg.pointTokenDomainName,
|
|
2104
|
+
chainId: request.chainId,
|
|
2105
|
+
verifyingContract: request.pointTokenAddress
|
|
2106
|
+
};
|
|
2107
|
+
let userOp;
|
|
2108
|
+
try {
|
|
2109
|
+
userOp = await this.cfg.relayService.prepareMint({
|
|
2110
|
+
userAddress: request.userAddress,
|
|
2111
|
+
aaNonce: request.aaNonce,
|
|
2112
|
+
batchExecutorAddress,
|
|
2113
|
+
pointTokenAddress: request.pointTokenAddress,
|
|
2114
|
+
amount: request.amount,
|
|
2115
|
+
issuerSignerWallet: this.cfg.issuerSignerWallet,
|
|
2116
|
+
domain,
|
|
2117
|
+
mintRequestNonce: request.mintRequestNonce,
|
|
2118
|
+
deadline: signatureDeadline
|
|
2119
|
+
// No feeAmount/feeRecipient — RelayService auto-resolves.
|
|
2120
|
+
});
|
|
2121
|
+
} catch (err) {
|
|
2122
|
+
throw new PTClaimError(
|
|
2123
|
+
"BUILD_FAILED",
|
|
2124
|
+
`prepareMint failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2125
|
+
);
|
|
2126
|
+
}
|
|
2127
|
+
let fallback;
|
|
2128
|
+
if (feeAmount > 0n) {
|
|
2129
|
+
try {
|
|
2130
|
+
fallback = await this.cfg.relayService.prepareMint({
|
|
2131
|
+
userAddress: request.userAddress,
|
|
2132
|
+
aaNonce: request.aaNonce,
|
|
2133
|
+
batchExecutorAddress,
|
|
2134
|
+
pointTokenAddress: request.pointTokenAddress,
|
|
2135
|
+
amount: request.amount,
|
|
2136
|
+
issuerSignerWallet: this.cfg.issuerSignerWallet,
|
|
2137
|
+
domain,
|
|
2138
|
+
mintRequestNonce: request.mintRequestNonce,
|
|
2139
|
+
deadline: signatureDeadline,
|
|
2140
|
+
feeAmount: 0n
|
|
2141
|
+
});
|
|
2142
|
+
} catch (err) {
|
|
2143
|
+
throw new PTClaimError(
|
|
2144
|
+
"BUILD_FAILED",
|
|
2145
|
+
`prepareMint (fallback) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2146
|
+
);
|
|
2147
|
+
}
|
|
2148
|
+
}
|
|
2149
|
+
const calls = (0, import_core9.decodeBatchExecuteCalls)(userOp.callData);
|
|
2150
|
+
const callsFallback = fallback ? (0, import_core9.decodeBatchExecuteCalls)(fallback.callData) : void 0;
|
|
2151
|
+
return {
|
|
2152
|
+
userOp,
|
|
2153
|
+
fallback,
|
|
2154
|
+
lockId,
|
|
2155
|
+
feeAmount,
|
|
2156
|
+
signatureDeadline,
|
|
2157
|
+
expiresInSeconds: Math.floor(this.cfg.lockDurationMs / 1e3),
|
|
2158
|
+
calls,
|
|
2159
|
+
callsFallback
|
|
2160
|
+
};
|
|
2161
|
+
}
|
|
2162
|
+
};
|
|
2163
|
+
|
|
2164
|
+
// src/api/handlers/swapHandler.ts
|
|
2165
|
+
var import_core10 = require("@pafi-dev/core");
|
|
2166
|
+
var SwapError = class extends Error {
|
|
2167
|
+
constructor(code, message) {
|
|
2168
|
+
super(message);
|
|
2169
|
+
this.code = code;
|
|
2170
|
+
this.name = "SwapError";
|
|
2171
|
+
}
|
|
2172
|
+
code;
|
|
2173
|
+
};
|
|
2174
|
+
var DEFAULT_SLIPPAGE_BPS = 50;
|
|
2175
|
+
var DEFAULT_SWAP_DEADLINE_SEC = 5 * 60;
|
|
2176
|
+
var SwapHandler = class {
|
|
2177
|
+
cfg;
|
|
2178
|
+
constructor(config) {
|
|
2179
|
+
this.cfg = {
|
|
2180
|
+
...config,
|
|
2181
|
+
defaultSlippageBps: config.defaultSlippageBps ?? DEFAULT_SLIPPAGE_BPS,
|
|
2182
|
+
defaultSwapDeadlineSeconds: config.defaultSwapDeadlineSeconds ?? DEFAULT_SWAP_DEADLINE_SEC,
|
|
2183
|
+
now: config.now ?? (() => Date.now())
|
|
2184
|
+
};
|
|
2185
|
+
}
|
|
2186
|
+
async handle(request) {
|
|
2187
|
+
if (request.amountIn <= 0n) {
|
|
2188
|
+
throw new SwapError("INVALID_AMOUNT", "amountIn must be positive");
|
|
2189
|
+
}
|
|
2190
|
+
const slippageBps = request.slippageBps ?? this.cfg.defaultSlippageBps;
|
|
2191
|
+
const { usdt, pafiFeeRecipient, universalRouter } = (0, import_core10.getContractAddresses)(
|
|
2192
|
+
request.chainId
|
|
2193
|
+
);
|
|
2194
|
+
const poolsResponse = await this.cfg.poolsProvider({
|
|
2195
|
+
chainId: request.chainId,
|
|
2196
|
+
pointTokenAddress: request.pointTokenAddress
|
|
2197
|
+
});
|
|
2198
|
+
if (poolsResponse.pools.length === 0) {
|
|
2199
|
+
throw new SwapError(
|
|
2200
|
+
"QUOTE_UNAVAILABLE",
|
|
2201
|
+
"no liquidity pool found for this point token"
|
|
2202
|
+
);
|
|
2203
|
+
}
|
|
2204
|
+
let fallbackQuote;
|
|
2205
|
+
try {
|
|
2206
|
+
fallbackQuote = await (0, import_core10.findBestQuote)(
|
|
2207
|
+
this.cfg.provider,
|
|
2208
|
+
request.chainId,
|
|
2209
|
+
request.pointTokenAddress,
|
|
2210
|
+
usdt,
|
|
2211
|
+
request.amountIn,
|
|
2212
|
+
poolsResponse.pools
|
|
2213
|
+
);
|
|
2214
|
+
} catch {
|
|
2215
|
+
throw new SwapError(
|
|
2216
|
+
"QUOTE_UNAVAILABLE",
|
|
2217
|
+
"no swap path found for this point token"
|
|
2218
|
+
);
|
|
2219
|
+
}
|
|
2220
|
+
const estimatedUsdtOutFallback = fallbackQuote.bestRoute.amountOut;
|
|
2221
|
+
const minAmountOutFallback = estimatedUsdtOutFallback * BigInt(1e4 - slippageBps) / 10000n;
|
|
2222
|
+
const deadline = request.deadline ?? BigInt(
|
|
2223
|
+
Math.floor(this.cfg.now() / 1e3) + this.cfg.defaultSwapDeadlineSeconds
|
|
2224
|
+
);
|
|
2225
|
+
const feeAmount = this.cfg.feeService ? await this.cfg.feeService.estimateGasFee() : 0n;
|
|
2226
|
+
if (feeAmount > 0n && feeAmount >= request.amountIn) {
|
|
2227
|
+
throw new SwapError(
|
|
2228
|
+
"FEE_EXCEEDS_AMOUNT",
|
|
2229
|
+
`gas fee (${feeAmount}) must be strictly less than swap amount (${request.amountIn})`
|
|
2230
|
+
);
|
|
2231
|
+
}
|
|
2232
|
+
const sponsoredAmountIn = request.amountIn - feeAmount;
|
|
2233
|
+
let estimatedUsdtOutSponsored = estimatedUsdtOutFallback;
|
|
2234
|
+
let sponsoredPath = fallbackQuote.bestRoute.path;
|
|
2235
|
+
if (feeAmount > 0n) {
|
|
2236
|
+
try {
|
|
2237
|
+
const sponsoredQuote = await (0, import_core10.findBestQuote)(
|
|
2238
|
+
this.cfg.provider,
|
|
2239
|
+
request.chainId,
|
|
2240
|
+
request.pointTokenAddress,
|
|
2241
|
+
usdt,
|
|
2242
|
+
sponsoredAmountIn,
|
|
2243
|
+
poolsResponse.pools
|
|
2244
|
+
);
|
|
2245
|
+
estimatedUsdtOutSponsored = sponsoredQuote.bestRoute.amountOut;
|
|
2246
|
+
sponsoredPath = sponsoredQuote.bestRoute.path;
|
|
2247
|
+
} catch {
|
|
2248
|
+
throw new SwapError(
|
|
2249
|
+
"QUOTE_UNAVAILABLE",
|
|
2250
|
+
"no swap path found for sponsored amount (after fee deduction)"
|
|
2251
|
+
);
|
|
2252
|
+
}
|
|
2253
|
+
}
|
|
2254
|
+
const minAmountOutSponsored = estimatedUsdtOutSponsored * BigInt(1e4 - slippageBps) / 10000n;
|
|
2255
|
+
const sponsoredOp = (0, import_core10.buildSwapWithGasDeduction)({
|
|
2256
|
+
userAddress: request.userAddress,
|
|
2257
|
+
aaNonce: request.aaNonce,
|
|
2258
|
+
pointTokenAddress: request.pointTokenAddress,
|
|
2259
|
+
outputTokenAddress: usdt,
|
|
2260
|
+
universalRouterAddress: universalRouter,
|
|
2261
|
+
amountIn: sponsoredAmountIn,
|
|
2262
|
+
minAmountOut: minAmountOutSponsored,
|
|
2263
|
+
swapPath: sponsoredPath,
|
|
2264
|
+
deadline,
|
|
2265
|
+
gasFeePt: feeAmount,
|
|
2266
|
+
feeRecipient: pafiFeeRecipient
|
|
2267
|
+
});
|
|
2268
|
+
const fallbackOp = feeAmount > 0n ? (0, import_core10.buildSwapWithGasDeduction)({
|
|
2269
|
+
userAddress: request.userAddress,
|
|
2270
|
+
aaNonce: request.aaNonce,
|
|
2271
|
+
pointTokenAddress: request.pointTokenAddress,
|
|
2272
|
+
outputTokenAddress: usdt,
|
|
2273
|
+
universalRouterAddress: universalRouter,
|
|
2274
|
+
amountIn: request.amountIn,
|
|
2275
|
+
minAmountOut: minAmountOutFallback,
|
|
2276
|
+
swapPath: fallbackQuote.bestRoute.path,
|
|
2277
|
+
deadline,
|
|
2278
|
+
gasFeePt: 0n,
|
|
2279
|
+
feeRecipient: pafiFeeRecipient
|
|
2280
|
+
}) : void 0;
|
|
2281
|
+
return {
|
|
2282
|
+
userOp: sponsoredOp,
|
|
2283
|
+
fallback: fallbackOp,
|
|
2284
|
+
feeAmount,
|
|
2285
|
+
estimatedUsdtOut: estimatedUsdtOutSponsored,
|
|
2286
|
+
minAmountOut: minAmountOutSponsored,
|
|
2287
|
+
estimatedUsdtOutFallback: fallbackOp ? estimatedUsdtOutFallback : void 0,
|
|
2288
|
+
minAmountOutFallback: fallbackOp ? minAmountOutFallback : void 0,
|
|
2289
|
+
deadline,
|
|
2290
|
+
calls: (0, import_core10.decodeBatchExecuteCalls)(sponsoredOp.callData),
|
|
2291
|
+
callsFallback: fallbackOp ? (0, import_core10.decodeBatchExecuteCalls)(fallbackOp.callData) : void 0
|
|
2292
|
+
};
|
|
2293
|
+
}
|
|
2294
|
+
};
|
|
2295
|
+
|
|
2296
|
+
// src/api/handlers/perpDepositHandler.ts
|
|
2297
|
+
var import_core11 = require("@pafi-dev/core");
|
|
2298
|
+
var PerpDepositError = class extends Error {
|
|
2299
|
+
constructor(code, message) {
|
|
2300
|
+
super(message);
|
|
2301
|
+
this.code = code;
|
|
2302
|
+
this.name = "PerpDepositError";
|
|
2303
|
+
}
|
|
2304
|
+
code;
|
|
2305
|
+
};
|
|
2306
|
+
var DEFAULT_MAX_FEE_PREMIUM_BPS = 5e3;
|
|
2307
|
+
var PerpDepositHandler = class {
|
|
2308
|
+
cfg;
|
|
2309
|
+
constructor(config) {
|
|
2310
|
+
this.cfg = {
|
|
2311
|
+
...config,
|
|
2312
|
+
maxFeePremiumBps: config.maxFeePremiumBps ?? DEFAULT_MAX_FEE_PREMIUM_BPS
|
|
2313
|
+
};
|
|
2314
|
+
}
|
|
2315
|
+
async handle(request) {
|
|
2316
|
+
if (request.amount <= 0n) {
|
|
2317
|
+
throw new PerpDepositError("INVALID_AMOUNT", "amount must be positive");
|
|
2318
|
+
}
|
|
2319
|
+
const brokerHash = import_core11.BROKER_HASHES[request.brokerId];
|
|
2320
|
+
const tokenHash = import_core11.TOKEN_HASHES.USDC;
|
|
2321
|
+
const vault = import_core11.ORDERLY_VAULT_ADDRESSES[request.chainId];
|
|
2322
|
+
if (!vault) {
|
|
2323
|
+
throw new PerpDepositError(
|
|
2324
|
+
"PERP_DEPOSIT_UNAVAILABLE",
|
|
2325
|
+
`no Orderly Vault for chainId ${request.chainId}`
|
|
2326
|
+
);
|
|
2327
|
+
}
|
|
2328
|
+
const { orderlyRelay: relayAddress, pafiFeeRecipient } = (0, import_core11.getContractAddresses)(request.chainId);
|
|
2329
|
+
const [usdcAddress, brokerAllowed] = await Promise.all([
|
|
2330
|
+
this.cfg.provider.readContract({
|
|
2331
|
+
address: vault,
|
|
2332
|
+
abi: import_core11.ORDERLY_VAULT_ABI,
|
|
2333
|
+
functionName: "getAllowedToken",
|
|
2334
|
+
args: [tokenHash]
|
|
2335
|
+
}),
|
|
2336
|
+
this.cfg.provider.readContract({
|
|
2337
|
+
address: vault,
|
|
2338
|
+
abi: import_core11.ORDERLY_VAULT_ABI,
|
|
2339
|
+
functionName: "getAllowedBroker",
|
|
2340
|
+
args: [brokerHash]
|
|
2341
|
+
})
|
|
2342
|
+
]);
|
|
2343
|
+
if (!brokerAllowed) {
|
|
2344
|
+
throw new PerpDepositError(
|
|
2345
|
+
"BROKER_NOT_WHITELISTED",
|
|
2346
|
+
`broker "${request.brokerId}" is not whitelisted on Orderly Vault`
|
|
2347
|
+
);
|
|
2348
|
+
}
|
|
2349
|
+
const accountId = (0, import_core11.computeAccountId)(request.userAddress, brokerHash);
|
|
2350
|
+
const requestForQuote = {
|
|
2351
|
+
token: usdcAddress,
|
|
2352
|
+
receiver: request.userAddress,
|
|
2353
|
+
brokerHash,
|
|
2354
|
+
totalAmount: request.amount,
|
|
2355
|
+
maxFee: 0n
|
|
2356
|
+
};
|
|
2357
|
+
const [relayTokenFee, ptGasFee] = await Promise.all([
|
|
2358
|
+
this.cfg.provider.readContract({
|
|
2359
|
+
address: relayAddress,
|
|
2360
|
+
abi: import_core11.ORDERLY_RELAY_ABI,
|
|
2361
|
+
functionName: "quoteTokenFee",
|
|
2362
|
+
args: [requestForQuote]
|
|
2363
|
+
}),
|
|
2364
|
+
this.cfg.feeService ? this.cfg.feeService.estimateGasFee() : Promise.resolve(0n)
|
|
2365
|
+
]);
|
|
2366
|
+
if (relayTokenFee >= request.amount) {
|
|
2367
|
+
throw new PerpDepositError(
|
|
2368
|
+
"RELAY_FEE_EXCEEDS_AMOUNT",
|
|
2369
|
+
`Relay quoted fee ${relayTokenFee} >= deposit amount ${request.amount}`
|
|
2370
|
+
);
|
|
2371
|
+
}
|
|
2372
|
+
const maxFee = relayTokenFee * BigInt(1e4 + this.cfg.maxFeePremiumBps) / 10000n;
|
|
2373
|
+
const depositReq = {
|
|
2374
|
+
token: usdcAddress,
|
|
2375
|
+
receiver: request.userAddress,
|
|
2376
|
+
brokerHash,
|
|
2377
|
+
totalAmount: request.amount,
|
|
2378
|
+
maxFee
|
|
2379
|
+
};
|
|
2380
|
+
const sponsoredOp = (0, import_core11.buildPerpDepositViaRelay)({
|
|
2381
|
+
userAddress: request.userAddress,
|
|
2382
|
+
aaNonce: request.aaNonce,
|
|
2383
|
+
relayAddress,
|
|
2384
|
+
request: depositReq,
|
|
2385
|
+
pointTokenAddress: this.cfg.pointTokenAddress,
|
|
2386
|
+
gasFeePt: ptGasFee,
|
|
2387
|
+
gasFeePtRecipient: pafiFeeRecipient
|
|
2388
|
+
});
|
|
2389
|
+
const fallbackOp = ptGasFee > 0n ? (0, import_core11.buildPerpDepositViaRelay)({
|
|
2390
|
+
userAddress: request.userAddress,
|
|
2391
|
+
aaNonce: request.aaNonce,
|
|
2392
|
+
relayAddress,
|
|
2393
|
+
request: depositReq
|
|
2394
|
+
}) : void 0;
|
|
2395
|
+
return {
|
|
2396
|
+
userOp: sponsoredOp,
|
|
2397
|
+
fallback: fallbackOp,
|
|
2398
|
+
feeAmount: ptGasFee,
|
|
2399
|
+
relayTokenFee,
|
|
2400
|
+
maxFee,
|
|
2401
|
+
netDeposit: request.amount - relayTokenFee,
|
|
2402
|
+
accountId,
|
|
2403
|
+
brokerHash,
|
|
2404
|
+
usdcAddress,
|
|
2405
|
+
relayAddress,
|
|
2406
|
+
calls: (0, import_core11.decodeBatchExecuteCalls)(sponsoredOp.callData),
|
|
2407
|
+
callsFallback: fallbackOp ? (0, import_core11.decodeBatchExecuteCalls)(fallbackOp.callData) : void 0
|
|
2408
|
+
};
|
|
2409
|
+
}
|
|
2410
|
+
};
|
|
2411
|
+
|
|
2412
|
+
// src/pools/subgraphPoolsProvider.ts
|
|
2413
|
+
var import_viem10 = require("viem");
|
|
2414
|
+
var import_core12 = require("@pafi-dev/core");
|
|
1749
2415
|
var DEFAULT_CACHE_TTL_MS = 3e4;
|
|
1750
2416
|
var POOL_QUERY = `
|
|
1751
2417
|
query GetPoolForPointToken($id: ID!) {
|
|
@@ -1763,7 +2429,7 @@ var POOL_QUERY = `
|
|
|
1763
2429
|
}
|
|
1764
2430
|
`;
|
|
1765
2431
|
function createSubgraphPoolsProvider(config = {}) {
|
|
1766
|
-
const subgraphUrl = config.subgraphUrl ??
|
|
2432
|
+
const subgraphUrl = config.subgraphUrl ?? import_core12.PAFI_SUBGRAPH_URL;
|
|
1767
2433
|
try {
|
|
1768
2434
|
const parsed = new URL(subgraphUrl);
|
|
1769
2435
|
if (process.env.NODE_ENV === "production" && parsed.protocol !== "https:") {
|
|
@@ -1845,7 +2511,7 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress)
|
|
|
1845
2511
|
return [];
|
|
1846
2512
|
}
|
|
1847
2513
|
const { pool } = token;
|
|
1848
|
-
if (!(0,
|
|
2514
|
+
if (!(0, import_viem10.isAddress)(pool.hooks)) {
|
|
1849
2515
|
console.error(
|
|
1850
2516
|
"[PAFI] SubgraphPoolsProvider: invalid hooks address in response:",
|
|
1851
2517
|
pool.hooks,
|
|
@@ -1853,7 +2519,7 @@ async function fetchPoolsFromSubgraph(fetchImpl, subgraphUrl, pointTokenAddress)
|
|
|
1853
2519
|
);
|
|
1854
2520
|
return [];
|
|
1855
2521
|
}
|
|
1856
|
-
if (!(0,
|
|
2522
|
+
if (!(0, import_viem10.isAddress)(pool.token0.id) || !(0, import_viem10.isAddress)(pool.token1.id)) {
|
|
1857
2523
|
console.error(
|
|
1858
2524
|
"[PAFI] SubgraphPoolsProvider: invalid token address in response \u2014 skipping pool"
|
|
1859
2525
|
);
|
|
@@ -1895,7 +2561,7 @@ var PRICE_QUERY = `
|
|
|
1895
2561
|
}
|
|
1896
2562
|
`;
|
|
1897
2563
|
function createSubgraphNativeUsdtQuoter(config = {}) {
|
|
1898
|
-
const subgraphUrl = config.subgraphUrl ??
|
|
2564
|
+
const subgraphUrl = config.subgraphUrl ?? import_core12.PAFI_SUBGRAPH_URL;
|
|
1899
2565
|
try {
|
|
1900
2566
|
const parsed = new URL(subgraphUrl);
|
|
1901
2567
|
if (process.env.NODE_ENV === "production" && parsed.protocol !== "https:") {
|
|
@@ -2003,8 +2669,8 @@ function toUsdtPerNative(priceFloat, usdtDecimals) {
|
|
|
2003
2669
|
}
|
|
2004
2670
|
|
|
2005
2671
|
// src/pools/nativePtQuoter.ts
|
|
2006
|
-
var
|
|
2007
|
-
var CHAINLINK_ABI = (0,
|
|
2672
|
+
var import_viem11 = require("viem");
|
|
2673
|
+
var CHAINLINK_ABI = (0, import_viem11.parseAbi)([
|
|
2008
2674
|
"function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)"
|
|
2009
2675
|
]);
|
|
2010
2676
|
var CHAINLINK_MAX_AGE_S = 3600n;
|
|
@@ -2025,7 +2691,7 @@ function createNativePtQuoter(config) {
|
|
|
2025
2691
|
provider,
|
|
2026
2692
|
pointTokenAddress,
|
|
2027
2693
|
chainlinkFeedAddress = "0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70",
|
|
2028
|
-
subgraphUrl =
|
|
2694
|
+
subgraphUrl = import_core12.PAFI_SUBGRAPH_URL,
|
|
2029
2695
|
cacheTtlMs = 3e4,
|
|
2030
2696
|
fallbackEthPriceUsd = 3e3,
|
|
2031
2697
|
fallbackPtPriceUsdt = 0.1,
|
|
@@ -2107,7 +2773,7 @@ function parseBigDecimalTo18(s) {
|
|
|
2107
2773
|
}
|
|
2108
2774
|
|
|
2109
2775
|
// src/balance/balanceAggregator.ts
|
|
2110
|
-
var
|
|
2776
|
+
var import_core13 = require("@pafi-dev/core");
|
|
2111
2777
|
var BalanceAggregator = class {
|
|
2112
2778
|
provider;
|
|
2113
2779
|
ledger;
|
|
@@ -2128,7 +2794,7 @@ var BalanceAggregator = class {
|
|
|
2128
2794
|
async getCombinedBalance(user, pointToken) {
|
|
2129
2795
|
const [offChain, onChain] = await Promise.all([
|
|
2130
2796
|
this.ledger.getBalance(user, pointToken),
|
|
2131
|
-
(0,
|
|
2797
|
+
(0, import_core13.getPointTokenBalance)(this.provider, pointToken, user)
|
|
2132
2798
|
]);
|
|
2133
2799
|
return {
|
|
2134
2800
|
offChain,
|
|
@@ -2361,8 +3027,8 @@ var PafiBackendClient = class {
|
|
|
2361
3027
|
};
|
|
2362
3028
|
|
|
2363
3029
|
// src/config.ts
|
|
2364
|
-
var
|
|
2365
|
-
var
|
|
3030
|
+
var import_viem12 = require("viem");
|
|
3031
|
+
var import_core14 = require("@pafi-dev/core");
|
|
2366
3032
|
function createIssuerService(config) {
|
|
2367
3033
|
if (!config.provider) {
|
|
2368
3034
|
throw new Error("createIssuerService: provider is required");
|
|
@@ -2382,7 +3048,7 @@ function createIssuerService(config) {
|
|
|
2382
3048
|
"createIssuerService: at least one of pointTokenAddress / pointTokenAddresses is required"
|
|
2383
3049
|
);
|
|
2384
3050
|
}
|
|
2385
|
-
const tokenAddresses = rawAddresses.map((a) => (0,
|
|
3051
|
+
const tokenAddresses = rawAddresses.map((a) => (0, import_viem12.getAddress)(a));
|
|
2386
3052
|
const ledger = config.ledger;
|
|
2387
3053
|
const sessionStore = config.sessionStore ?? new MemorySessionStore();
|
|
2388
3054
|
const policy = config.policy ?? new DefaultPolicyEngine({ ledger });
|
|
@@ -2432,7 +3098,7 @@ function createIssuerService(config) {
|
|
|
2432
3098
|
indexers.set(tokenAddress, new PointIndexer(indexerConfig));
|
|
2433
3099
|
}
|
|
2434
3100
|
const firstIndexer = indexers.get(tokenAddresses[0]);
|
|
2435
|
-
const chainAddresses = (0,
|
|
3101
|
+
const chainAddresses = (0, import_core14.getContractAddresses)(config.chainId);
|
|
2436
3102
|
const resolvedContracts = {
|
|
2437
3103
|
batchExecutor: chainAddresses.batchExecutor,
|
|
2438
3104
|
usdt: chainAddresses.usdt,
|
|
@@ -2479,156 +3145,9 @@ function createIssuerService(config) {
|
|
|
2479
3145
|
};
|
|
2480
3146
|
}
|
|
2481
3147
|
|
|
2482
|
-
// src/userop-store/serialize.ts
|
|
2483
|
-
var import_core9 = require("@pafi-dev/core");
|
|
2484
|
-
function serializeEntryToJsonRpc(entry, signature, variant = "sponsored") {
|
|
2485
|
-
if (variant === "fallback") {
|
|
2486
|
-
if (!entry.fallback) {
|
|
2487
|
-
throw new Error(
|
|
2488
|
-
"serializeEntryToJsonRpc: variant=fallback requested but the stored entry has no `fallback` branch \u2014 caller should resubmit with variant='sponsored' or re-prepare with a fee configured."
|
|
2489
|
-
);
|
|
2490
|
-
}
|
|
2491
|
-
return (0, import_core9.serializeUserOpToJsonRpc)(
|
|
2492
|
-
{
|
|
2493
|
-
sender: entry.sender,
|
|
2494
|
-
nonce: BigInt(entry.nonce),
|
|
2495
|
-
callData: entry.fallback.callData,
|
|
2496
|
-
callGasLimit: BigInt(entry.fallback.callGasLimit),
|
|
2497
|
-
verificationGasLimit: BigInt(entry.fallback.verificationGasLimit),
|
|
2498
|
-
preVerificationGas: BigInt(entry.fallback.preVerificationGas),
|
|
2499
|
-
maxFeePerGas: BigInt(entry.maxFeePerGas),
|
|
2500
|
-
maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas)
|
|
2501
|
-
// intentionally no paymaster — user pays ETH gas
|
|
2502
|
-
},
|
|
2503
|
-
signature
|
|
2504
|
-
);
|
|
2505
|
-
}
|
|
2506
|
-
return (0, import_core9.serializeUserOpToJsonRpc)(
|
|
2507
|
-
{
|
|
2508
|
-
sender: entry.sender,
|
|
2509
|
-
nonce: BigInt(entry.nonce),
|
|
2510
|
-
callData: entry.callData,
|
|
2511
|
-
callGasLimit: BigInt(entry.callGasLimit),
|
|
2512
|
-
verificationGasLimit: BigInt(entry.verificationGasLimit),
|
|
2513
|
-
preVerificationGas: BigInt(entry.preVerificationGas),
|
|
2514
|
-
maxFeePerGas: BigInt(entry.maxFeePerGas),
|
|
2515
|
-
maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas),
|
|
2516
|
-
paymaster: entry.paymaster,
|
|
2517
|
-
paymasterVerificationGasLimit: entry.paymasterVerificationGasLimit != null ? BigInt(entry.paymasterVerificationGasLimit) : void 0,
|
|
2518
|
-
paymasterPostOpGasLimit: entry.paymasterPostOpGasLimit != null ? BigInt(entry.paymasterPostOpGasLimit) : void 0,
|
|
2519
|
-
paymasterData: entry.paymasterData
|
|
2520
|
-
},
|
|
2521
|
-
signature
|
|
2522
|
-
);
|
|
2523
|
-
}
|
|
2524
|
-
|
|
2525
|
-
// src/userop-store/prepareUserOp.ts
|
|
2526
|
-
var import_core10 = require("@pafi-dev/core");
|
|
2527
|
-
function serializeUserOpTypedData(td) {
|
|
2528
|
-
return {
|
|
2529
|
-
domain: td.domain,
|
|
2530
|
-
types: td.types,
|
|
2531
|
-
primaryType: td.primaryType,
|
|
2532
|
-
message: {
|
|
2533
|
-
sender: td.message.sender,
|
|
2534
|
-
nonce: `0x${td.message.nonce.toString(16)}`,
|
|
2535
|
-
initCode: td.message.initCode,
|
|
2536
|
-
callData: td.message.callData,
|
|
2537
|
-
accountGasLimits: td.message.accountGasLimits,
|
|
2538
|
-
preVerificationGas: `0x${td.message.preVerificationGas.toString(
|
|
2539
|
-
16
|
|
2540
|
-
)}`,
|
|
2541
|
-
gasFees: td.message.gasFees,
|
|
2542
|
-
paymasterAndData: td.message.paymasterAndData
|
|
2543
|
-
}
|
|
2544
|
-
};
|
|
2545
|
-
}
|
|
2546
|
-
function mergePaymasterFields(userOp, paymasterFields) {
|
|
2547
|
-
if (!paymasterFields) return userOp;
|
|
2548
|
-
const merged = {
|
|
2549
|
-
...userOp
|
|
2550
|
-
};
|
|
2551
|
-
for (const [k, v] of Object.entries(paymasterFields)) {
|
|
2552
|
-
if (v !== void 0) merged[k] = v;
|
|
2553
|
-
}
|
|
2554
|
-
return merged;
|
|
2555
|
-
}
|
|
2556
|
-
async function prepareMobileUserOp(params) {
|
|
2557
|
-
const userOp = mergePaymasterFields(
|
|
2558
|
-
params.partialUserOp,
|
|
2559
|
-
params.paymasterFields
|
|
2560
|
-
);
|
|
2561
|
-
const userOpHash = (0, import_core10.computeUserOpHash)(userOp, params.chainId);
|
|
2562
|
-
const typedData = serializeUserOpTypedData(
|
|
2563
|
-
(0, import_core10.buildUserOpTypedData)(userOp, params.chainId)
|
|
2564
|
-
);
|
|
2565
|
-
let fallback;
|
|
2566
|
-
let fallbackEntry;
|
|
2567
|
-
if (params.partialUserOpFallback) {
|
|
2568
|
-
const fallbackUserOp = {
|
|
2569
|
-
...params.partialUserOpFallback,
|
|
2570
|
-
maxFeePerGas: userOp.maxFeePerGas,
|
|
2571
|
-
maxPriorityFeePerGas: userOp.maxPriorityFeePerGas
|
|
2572
|
-
};
|
|
2573
|
-
const fallbackHash = (0, import_core10.computeUserOpHash)(fallbackUserOp, params.chainId);
|
|
2574
|
-
const fallbackTypedData = serializeUserOpTypedData(
|
|
2575
|
-
(0, import_core10.buildUserOpTypedData)(fallbackUserOp, params.chainId)
|
|
2576
|
-
);
|
|
2577
|
-
fallback = {
|
|
2578
|
-
userOp: fallbackUserOp,
|
|
2579
|
-
userOpHash: fallbackHash,
|
|
2580
|
-
typedData: fallbackTypedData
|
|
2581
|
-
};
|
|
2582
|
-
fallbackEntry = {
|
|
2583
|
-
callData: fallbackUserOp.callData,
|
|
2584
|
-
callGasLimit: fallbackUserOp.callGasLimit.toString(),
|
|
2585
|
-
verificationGasLimit: fallbackUserOp.verificationGasLimit.toString(),
|
|
2586
|
-
preVerificationGas: fallbackUserOp.preVerificationGas.toString(),
|
|
2587
|
-
userOpHash: fallbackHash
|
|
2588
|
-
};
|
|
2589
|
-
}
|
|
2590
|
-
const entry = {
|
|
2591
|
-
sender: userOp.sender,
|
|
2592
|
-
nonce: userOp.nonce.toString(),
|
|
2593
|
-
callData: userOp.callData,
|
|
2594
|
-
callGasLimit: userOp.callGasLimit.toString(),
|
|
2595
|
-
verificationGasLimit: userOp.verificationGasLimit.toString(),
|
|
2596
|
-
preVerificationGas: userOp.preVerificationGas.toString(),
|
|
2597
|
-
maxFeePerGas: userOp.maxFeePerGas.toString(),
|
|
2598
|
-
maxPriorityFeePerGas: userOp.maxPriorityFeePerGas.toString(),
|
|
2599
|
-
paymaster: userOp.paymaster,
|
|
2600
|
-
paymasterVerificationGasLimit: userOp.paymasterVerificationGasLimit?.toString(),
|
|
2601
|
-
paymasterPostOpGasLimit: userOp.paymasterPostOpGasLimit?.toString(),
|
|
2602
|
-
paymasterData: userOp.paymasterData,
|
|
2603
|
-
chainId: params.chainId,
|
|
2604
|
-
userOpHash,
|
|
2605
|
-
fallback: fallbackEntry
|
|
2606
|
-
};
|
|
2607
|
-
await params.store.save(params.lockId, entry, params.ttlSeconds);
|
|
2608
|
-
return {
|
|
2609
|
-
sponsored: { userOp, userOpHash, typedData },
|
|
2610
|
-
fallback,
|
|
2611
|
-
entry
|
|
2612
|
-
};
|
|
2613
|
-
}
|
|
2614
|
-
|
|
2615
|
-
// src/issuer-state/validator.ts
|
|
2616
|
-
var import_viem12 = require("viem");
|
|
2617
|
-
var import_core11 = require("@pafi-dev/core");
|
|
2618
|
-
|
|
2619
|
-
// src/issuer-state/types.ts
|
|
2620
|
-
var IssuerStateError = class extends Error {
|
|
2621
|
-
constructor(code, message, details) {
|
|
2622
|
-
super(message);
|
|
2623
|
-
this.code = code;
|
|
2624
|
-
this.details = details;
|
|
2625
|
-
this.name = "IssuerStateError";
|
|
2626
|
-
}
|
|
2627
|
-
code;
|
|
2628
|
-
details;
|
|
2629
|
-
};
|
|
2630
|
-
|
|
2631
3148
|
// src/issuer-state/validator.ts
|
|
3149
|
+
var import_viem13 = require("viem");
|
|
3150
|
+
var import_core15 = require("@pafi-dev/core");
|
|
2632
3151
|
var ISSUER_RECORD_TTL_MS = 3e4;
|
|
2633
3152
|
var IssuerStateValidator = class _IssuerStateValidator {
|
|
2634
3153
|
constructor(provider, registryAddress) {
|
|
@@ -2645,7 +3164,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2645
3164
|
* `CONTRACT_ADDRESSES` map for the given chain.
|
|
2646
3165
|
*/
|
|
2647
3166
|
static forChain(provider, chainId) {
|
|
2648
|
-
const { issuerRegistry } = (0,
|
|
3167
|
+
const { issuerRegistry } = (0, import_core15.getContractAddresses)(chainId);
|
|
2649
3168
|
return new _IssuerStateValidator(provider, issuerRegistry);
|
|
2650
3169
|
}
|
|
2651
3170
|
/**
|
|
@@ -2654,7 +3173,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2654
3173
|
*/
|
|
2655
3174
|
invalidate(pointToken) {
|
|
2656
3175
|
if (pointToken) {
|
|
2657
|
-
const key = (0,
|
|
3176
|
+
const key = (0, import_viem13.getAddress)(pointToken);
|
|
2658
3177
|
this.pointTokenIssuerCache.delete(key);
|
|
2659
3178
|
this.stateCache.delete(key);
|
|
2660
3179
|
this.inflight.delete(key);
|
|
@@ -2669,23 +3188,23 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2669
3188
|
* The issuer field is set at `initialize()` and never changes.
|
|
2670
3189
|
*/
|
|
2671
3190
|
async getIssuerAddressForPointToken(pointToken) {
|
|
2672
|
-
const key = (0,
|
|
3191
|
+
const key = (0, import_viem13.getAddress)(pointToken);
|
|
2673
3192
|
const cached = this.pointTokenIssuerCache.get(key);
|
|
2674
3193
|
if (cached) return cached;
|
|
2675
3194
|
const issuer = await this.provider.readContract({
|
|
2676
3195
|
address: key,
|
|
2677
|
-
abi:
|
|
3196
|
+
abi: import_core15.POINT_TOKEN_V2_ABI,
|
|
2678
3197
|
functionName: "issuer"
|
|
2679
3198
|
});
|
|
2680
|
-
this.pointTokenIssuerCache.set(key, (0,
|
|
2681
|
-
return (0,
|
|
3199
|
+
this.pointTokenIssuerCache.set(key, (0, import_viem13.getAddress)(issuer));
|
|
3200
|
+
return (0, import_viem13.getAddress)(issuer);
|
|
2682
3201
|
}
|
|
2683
3202
|
/**
|
|
2684
3203
|
* Read registry record + totalSupply, with 30s cache and in-flight
|
|
2685
3204
|
* deduplication. Does NOT throw on inactive/missing — returns raw state.
|
|
2686
3205
|
*/
|
|
2687
3206
|
async getIssuerState(pointToken) {
|
|
2688
|
-
const tokenAddr = (0,
|
|
3207
|
+
const tokenAddr = (0, import_viem13.getAddress)(pointToken);
|
|
2689
3208
|
const now = Date.now();
|
|
2690
3209
|
const cached = this.stateCache.get(tokenAddr);
|
|
2691
3210
|
if (cached && cached.expiresAt > now) return cached.value;
|
|
@@ -2755,13 +3274,13 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2755
3274
|
const [issuerTuple, totalSupply] = await Promise.all([
|
|
2756
3275
|
this.provider.readContract({
|
|
2757
3276
|
address: this.registryAddress,
|
|
2758
|
-
abi:
|
|
3277
|
+
abi: import_core15.issuerRegistryGetIssuerFlatAbi,
|
|
2759
3278
|
functionName: "getIssuer",
|
|
2760
3279
|
args: [issuerAddr]
|
|
2761
3280
|
}),
|
|
2762
3281
|
this.provider.readContract({
|
|
2763
3282
|
address: tokenAddr,
|
|
2764
|
-
abi:
|
|
3283
|
+
abi: import_core15.POINT_TOKEN_V2_ABI,
|
|
2765
3284
|
functionName: "totalSupply"
|
|
2766
3285
|
})
|
|
2767
3286
|
]);
|
|
@@ -2789,6 +3308,8 @@ var PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
|
2789
3308
|
AuthError,
|
|
2790
3309
|
AuthService,
|
|
2791
3310
|
BalanceAggregator,
|
|
3311
|
+
BundlerNotConfiguredError,
|
|
3312
|
+
BundlerRejectedError,
|
|
2792
3313
|
BurnIndexer,
|
|
2793
3314
|
DefaultPolicyEngine,
|
|
2794
3315
|
FeeManager,
|
|
@@ -2801,13 +3322,20 @@ var PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
|
2801
3322
|
NonceManager,
|
|
2802
3323
|
PAFI_ISSUER_SDK_VERSION,
|
|
2803
3324
|
PAFI_SUBGRAPH_URL,
|
|
3325
|
+
PTClaimError,
|
|
3326
|
+
PTClaimHandler,
|
|
2804
3327
|
PTRedeemError,
|
|
2805
3328
|
PTRedeemHandler,
|
|
2806
3329
|
PafiBackendClient,
|
|
2807
3330
|
PafiBackendError,
|
|
3331
|
+
PendingUserOpNotFoundError,
|
|
3332
|
+
PerpDepositError,
|
|
3333
|
+
PerpDepositHandler,
|
|
2808
3334
|
PointIndexer,
|
|
2809
3335
|
RelayError,
|
|
2810
3336
|
RelayService,
|
|
3337
|
+
SwapError,
|
|
3338
|
+
SwapHandler,
|
|
2811
3339
|
TopUpRedemptionError,
|
|
2812
3340
|
TopUpRedemptionHandler,
|
|
2813
3341
|
authenticateRequest,
|
|
@@ -2816,9 +3344,13 @@ var PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
|
2816
3344
|
createSubgraphNativeUsdtQuoter,
|
|
2817
3345
|
createSubgraphPoolsProvider,
|
|
2818
3346
|
handleClaimStatus,
|
|
3347
|
+
handleMobilePrepare,
|
|
3348
|
+
handleMobileSubmit,
|
|
2819
3349
|
handleRedeemStatus,
|
|
2820
3350
|
mergePaymasterFields,
|
|
2821
3351
|
prepareMobileUserOp,
|
|
3352
|
+
relayUserOp,
|
|
3353
|
+
requestPaymaster,
|
|
2822
3354
|
serializeEntryToJsonRpc,
|
|
2823
3355
|
serializeUserOpTypedData
|
|
2824
3356
|
});
|