@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.js
CHANGED
|
@@ -1698,6 +1698,683 @@ async function handleRedeemStatus(params) {
|
|
|
1698
1698
|
};
|
|
1699
1699
|
}
|
|
1700
1700
|
|
|
1701
|
+
// src/api/mobileHandlers.ts
|
|
1702
|
+
import {
|
|
1703
|
+
ENTRY_POINT_V08,
|
|
1704
|
+
parseEip7702DelegatedAddress
|
|
1705
|
+
} from "@pafi-dev/core";
|
|
1706
|
+
|
|
1707
|
+
// src/userop-store/serialize.ts
|
|
1708
|
+
import { serializeUserOpToJsonRpc } from "@pafi-dev/core";
|
|
1709
|
+
function serializeEntryToJsonRpc(entry, signature, variant = "sponsored") {
|
|
1710
|
+
if (variant === "fallback") {
|
|
1711
|
+
if (!entry.fallback) {
|
|
1712
|
+
throw new Error(
|
|
1713
|
+
"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."
|
|
1714
|
+
);
|
|
1715
|
+
}
|
|
1716
|
+
return serializeUserOpToJsonRpc(
|
|
1717
|
+
{
|
|
1718
|
+
sender: entry.sender,
|
|
1719
|
+
nonce: BigInt(entry.nonce),
|
|
1720
|
+
callData: entry.fallback.callData,
|
|
1721
|
+
callGasLimit: BigInt(entry.fallback.callGasLimit),
|
|
1722
|
+
verificationGasLimit: BigInt(entry.fallback.verificationGasLimit),
|
|
1723
|
+
preVerificationGas: BigInt(entry.fallback.preVerificationGas),
|
|
1724
|
+
maxFeePerGas: BigInt(entry.maxFeePerGas),
|
|
1725
|
+
maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas)
|
|
1726
|
+
// intentionally no paymaster — user pays ETH gas
|
|
1727
|
+
},
|
|
1728
|
+
signature
|
|
1729
|
+
);
|
|
1730
|
+
}
|
|
1731
|
+
return serializeUserOpToJsonRpc(
|
|
1732
|
+
{
|
|
1733
|
+
sender: entry.sender,
|
|
1734
|
+
nonce: BigInt(entry.nonce),
|
|
1735
|
+
callData: entry.callData,
|
|
1736
|
+
callGasLimit: BigInt(entry.callGasLimit),
|
|
1737
|
+
verificationGasLimit: BigInt(entry.verificationGasLimit),
|
|
1738
|
+
preVerificationGas: BigInt(entry.preVerificationGas),
|
|
1739
|
+
maxFeePerGas: BigInt(entry.maxFeePerGas),
|
|
1740
|
+
maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas),
|
|
1741
|
+
paymaster: entry.paymaster,
|
|
1742
|
+
paymasterVerificationGasLimit: entry.paymasterVerificationGasLimit != null ? BigInt(entry.paymasterVerificationGasLimit) : void 0,
|
|
1743
|
+
paymasterPostOpGasLimit: entry.paymasterPostOpGasLimit != null ? BigInt(entry.paymasterPostOpGasLimit) : void 0,
|
|
1744
|
+
paymasterData: entry.paymasterData
|
|
1745
|
+
},
|
|
1746
|
+
signature
|
|
1747
|
+
);
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
// src/userop-store/prepareUserOp.ts
|
|
1751
|
+
import {
|
|
1752
|
+
buildUserOpTypedData,
|
|
1753
|
+
computeUserOpHash
|
|
1754
|
+
} from "@pafi-dev/core";
|
|
1755
|
+
function serializeUserOpTypedData(td) {
|
|
1756
|
+
return {
|
|
1757
|
+
domain: td.domain,
|
|
1758
|
+
types: td.types,
|
|
1759
|
+
primaryType: td.primaryType,
|
|
1760
|
+
message: {
|
|
1761
|
+
sender: td.message.sender,
|
|
1762
|
+
nonce: `0x${td.message.nonce.toString(16)}`,
|
|
1763
|
+
initCode: td.message.initCode,
|
|
1764
|
+
callData: td.message.callData,
|
|
1765
|
+
accountGasLimits: td.message.accountGasLimits,
|
|
1766
|
+
preVerificationGas: `0x${td.message.preVerificationGas.toString(
|
|
1767
|
+
16
|
|
1768
|
+
)}`,
|
|
1769
|
+
gasFees: td.message.gasFees,
|
|
1770
|
+
paymasterAndData: td.message.paymasterAndData
|
|
1771
|
+
}
|
|
1772
|
+
};
|
|
1773
|
+
}
|
|
1774
|
+
function mergePaymasterFields(userOp, paymasterFields) {
|
|
1775
|
+
if (!paymasterFields) return userOp;
|
|
1776
|
+
const merged = {
|
|
1777
|
+
...userOp
|
|
1778
|
+
};
|
|
1779
|
+
for (const [k, v] of Object.entries(paymasterFields)) {
|
|
1780
|
+
if (v !== void 0) merged[k] = v;
|
|
1781
|
+
}
|
|
1782
|
+
return merged;
|
|
1783
|
+
}
|
|
1784
|
+
async function prepareMobileUserOp(params) {
|
|
1785
|
+
const userOp = mergePaymasterFields(
|
|
1786
|
+
params.partialUserOp,
|
|
1787
|
+
params.paymasterFields
|
|
1788
|
+
);
|
|
1789
|
+
const userOpHash = computeUserOpHash(userOp, params.chainId);
|
|
1790
|
+
const typedData = serializeUserOpTypedData(
|
|
1791
|
+
buildUserOpTypedData(userOp, params.chainId)
|
|
1792
|
+
);
|
|
1793
|
+
let fallback;
|
|
1794
|
+
let fallbackEntry;
|
|
1795
|
+
if (params.partialUserOpFallback) {
|
|
1796
|
+
const fallbackUserOp = {
|
|
1797
|
+
...params.partialUserOpFallback,
|
|
1798
|
+
maxFeePerGas: userOp.maxFeePerGas,
|
|
1799
|
+
maxPriorityFeePerGas: userOp.maxPriorityFeePerGas
|
|
1800
|
+
};
|
|
1801
|
+
const fallbackHash = computeUserOpHash(fallbackUserOp, params.chainId);
|
|
1802
|
+
const fallbackTypedData = serializeUserOpTypedData(
|
|
1803
|
+
buildUserOpTypedData(fallbackUserOp, params.chainId)
|
|
1804
|
+
);
|
|
1805
|
+
fallback = {
|
|
1806
|
+
userOp: fallbackUserOp,
|
|
1807
|
+
userOpHash: fallbackHash,
|
|
1808
|
+
typedData: fallbackTypedData
|
|
1809
|
+
};
|
|
1810
|
+
fallbackEntry = {
|
|
1811
|
+
callData: fallbackUserOp.callData,
|
|
1812
|
+
callGasLimit: fallbackUserOp.callGasLimit.toString(),
|
|
1813
|
+
verificationGasLimit: fallbackUserOp.verificationGasLimit.toString(),
|
|
1814
|
+
preVerificationGas: fallbackUserOp.preVerificationGas.toString(),
|
|
1815
|
+
userOpHash: fallbackHash
|
|
1816
|
+
};
|
|
1817
|
+
}
|
|
1818
|
+
const entry = {
|
|
1819
|
+
sender: userOp.sender,
|
|
1820
|
+
nonce: userOp.nonce.toString(),
|
|
1821
|
+
callData: userOp.callData,
|
|
1822
|
+
callGasLimit: userOp.callGasLimit.toString(),
|
|
1823
|
+
verificationGasLimit: userOp.verificationGasLimit.toString(),
|
|
1824
|
+
preVerificationGas: userOp.preVerificationGas.toString(),
|
|
1825
|
+
maxFeePerGas: userOp.maxFeePerGas.toString(),
|
|
1826
|
+
maxPriorityFeePerGas: userOp.maxPriorityFeePerGas.toString(),
|
|
1827
|
+
paymaster: userOp.paymaster,
|
|
1828
|
+
paymasterVerificationGasLimit: userOp.paymasterVerificationGasLimit?.toString(),
|
|
1829
|
+
paymasterPostOpGasLimit: userOp.paymasterPostOpGasLimit?.toString(),
|
|
1830
|
+
paymasterData: userOp.paymasterData,
|
|
1831
|
+
chainId: params.chainId,
|
|
1832
|
+
userOpHash,
|
|
1833
|
+
fallback: fallbackEntry
|
|
1834
|
+
};
|
|
1835
|
+
await params.store.save(params.lockId, entry, params.ttlSeconds);
|
|
1836
|
+
return {
|
|
1837
|
+
sponsored: { userOp, userOpHash, typedData },
|
|
1838
|
+
fallback,
|
|
1839
|
+
entry
|
|
1840
|
+
};
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
// src/pafi-backend/helpers.ts
|
|
1844
|
+
var BundlerNotConfiguredError = class extends Error {
|
|
1845
|
+
code = "BUNDLER_NOT_CONFIGURED";
|
|
1846
|
+
constructor() {
|
|
1847
|
+
super(
|
|
1848
|
+
"PAFI backend client not configured \u2014 set PAFI_BACKEND_URL, PAFI_ISSUER_ID, PAFI_API_KEY to enable mobile submit."
|
|
1849
|
+
);
|
|
1850
|
+
this.name = "BundlerNotConfiguredError";
|
|
1851
|
+
}
|
|
1852
|
+
};
|
|
1853
|
+
var BundlerRejectedError = class extends Error {
|
|
1854
|
+
code = "BUNDLER_REJECTED";
|
|
1855
|
+
cause;
|
|
1856
|
+
constructor(message, cause) {
|
|
1857
|
+
super(message);
|
|
1858
|
+
this.name = "BundlerRejectedError";
|
|
1859
|
+
this.cause = cause;
|
|
1860
|
+
}
|
|
1861
|
+
};
|
|
1862
|
+
async function requestPaymaster(params) {
|
|
1863
|
+
if (!params.client) return void 0;
|
|
1864
|
+
const fn = params.functionName ?? defaultFunctionForScenario(params.scenario);
|
|
1865
|
+
try {
|
|
1866
|
+
return await params.client.requestSponsorship({
|
|
1867
|
+
chainId: params.chainId,
|
|
1868
|
+
scenario: params.scenario,
|
|
1869
|
+
userOp: params.userOp,
|
|
1870
|
+
target: {
|
|
1871
|
+
contract: params.pointTokenAddress,
|
|
1872
|
+
function: fn,
|
|
1873
|
+
pointToken: params.pointTokenAddress
|
|
1874
|
+
}
|
|
1875
|
+
});
|
|
1876
|
+
} catch (err) {
|
|
1877
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1878
|
+
params.onWarning?.(`Paymaster sponsorship declined: ${msg}`);
|
|
1879
|
+
return void 0;
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1882
|
+
function defaultFunctionForScenario(scenario) {
|
|
1883
|
+
switch (scenario) {
|
|
1884
|
+
case "mint":
|
|
1885
|
+
return "mint";
|
|
1886
|
+
case "burn":
|
|
1887
|
+
return "burn";
|
|
1888
|
+
case "swap":
|
|
1889
|
+
return "swap";
|
|
1890
|
+
case "perp-deposit":
|
|
1891
|
+
return "deposit";
|
|
1892
|
+
default:
|
|
1893
|
+
return scenario;
|
|
1894
|
+
}
|
|
1895
|
+
}
|
|
1896
|
+
async function relayUserOp(params) {
|
|
1897
|
+
if (!params.client) {
|
|
1898
|
+
throw new BundlerNotConfiguredError();
|
|
1899
|
+
}
|
|
1900
|
+
try {
|
|
1901
|
+
const result = await params.client.relayUserOperation({
|
|
1902
|
+
userOp: params.userOp,
|
|
1903
|
+
entryPoint: params.entryPoint,
|
|
1904
|
+
eip7702Auth: params.eip7702Auth
|
|
1905
|
+
});
|
|
1906
|
+
return { userOpHash: result.userOpHash };
|
|
1907
|
+
} catch (err) {
|
|
1908
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1909
|
+
throw new BundlerRejectedError(msg, err);
|
|
1910
|
+
}
|
|
1911
|
+
}
|
|
1912
|
+
|
|
1913
|
+
// src/api/mobileHandlers.ts
|
|
1914
|
+
var PendingUserOpNotFoundError = class extends Error {
|
|
1915
|
+
code = "PENDING_USEROP_NOT_FOUND";
|
|
1916
|
+
constructor(lockId) {
|
|
1917
|
+
super(
|
|
1918
|
+
`No pending UserOp found for lockId ${lockId} \u2014 it may have expired or already been submitted.`
|
|
1919
|
+
);
|
|
1920
|
+
this.name = "PendingUserOpNotFoundError";
|
|
1921
|
+
}
|
|
1922
|
+
};
|
|
1923
|
+
async function handleMobilePrepare(params) {
|
|
1924
|
+
const [fees, userCode] = await Promise.all([
|
|
1925
|
+
params.provider.estimateFeesPerGas(),
|
|
1926
|
+
params.provider.getCode({ address: params.userAddress })
|
|
1927
|
+
]);
|
|
1928
|
+
const needsDelegation = parseEip7702DelegatedAddress(userCode) === null;
|
|
1929
|
+
const sponsoredOp = {
|
|
1930
|
+
...params.partialUserOp,
|
|
1931
|
+
maxFeePerGas: fees.maxFeePerGas ?? params.partialUserOp.maxFeePerGas ?? 0n,
|
|
1932
|
+
maxPriorityFeePerGas: fees.maxPriorityFeePerGas ?? params.partialUserOp.maxPriorityFeePerGas ?? 0n
|
|
1933
|
+
};
|
|
1934
|
+
const paymasterFields = await requestPaymaster({
|
|
1935
|
+
client: params.pafiBackendClient,
|
|
1936
|
+
chainId: params.chainId,
|
|
1937
|
+
scenario: params.scenario,
|
|
1938
|
+
userOp: sponsoredOp,
|
|
1939
|
+
pointTokenAddress: params.pointTokenAddress,
|
|
1940
|
+
onWarning: params.onWarning
|
|
1941
|
+
});
|
|
1942
|
+
const prepared = await prepareMobileUserOp({
|
|
1943
|
+
lockId: params.lockId,
|
|
1944
|
+
partialUserOp: sponsoredOp,
|
|
1945
|
+
partialUserOpFallback: params.partialUserOpFallback,
|
|
1946
|
+
paymasterFields,
|
|
1947
|
+
chainId: params.chainId,
|
|
1948
|
+
store: params.store,
|
|
1949
|
+
ttlSeconds: params.ttlSeconds
|
|
1950
|
+
});
|
|
1951
|
+
return {
|
|
1952
|
+
...prepared,
|
|
1953
|
+
isSponsored: !!paymasterFields,
|
|
1954
|
+
needsDelegation
|
|
1955
|
+
};
|
|
1956
|
+
}
|
|
1957
|
+
async function handleMobileSubmit(params) {
|
|
1958
|
+
const entry = await params.store.get(params.lockId);
|
|
1959
|
+
if (!entry) {
|
|
1960
|
+
throw new PendingUserOpNotFoundError(params.lockId);
|
|
1961
|
+
}
|
|
1962
|
+
const variant = params.variant ?? "sponsored";
|
|
1963
|
+
const userOpJson = serializeEntryToJsonRpc(entry, params.signature, variant);
|
|
1964
|
+
const result = await relayUserOp({
|
|
1965
|
+
client: params.pafiBackendClient,
|
|
1966
|
+
userOp: userOpJson,
|
|
1967
|
+
entryPoint: params.entryPoint ?? ENTRY_POINT_V08
|
|
1968
|
+
});
|
|
1969
|
+
await params.bindUserOpHash(params.lockId, result.userOpHash);
|
|
1970
|
+
await params.store.delete(params.lockId);
|
|
1971
|
+
return { userOpHash: result.userOpHash };
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
// src/api/handlers/ptClaimHandler.ts
|
|
1975
|
+
import { getAddress as getAddress8 } from "viem";
|
|
1976
|
+
import {
|
|
1977
|
+
decodeBatchExecuteCalls,
|
|
1978
|
+
getContractAddresses as getContractAddresses2
|
|
1979
|
+
} from "@pafi-dev/core";
|
|
1980
|
+
|
|
1981
|
+
// src/issuer-state/types.ts
|
|
1982
|
+
var IssuerStateError = class extends Error {
|
|
1983
|
+
constructor(code, message, details) {
|
|
1984
|
+
super(message);
|
|
1985
|
+
this.code = code;
|
|
1986
|
+
this.details = details;
|
|
1987
|
+
this.name = "IssuerStateError";
|
|
1988
|
+
}
|
|
1989
|
+
code;
|
|
1990
|
+
details;
|
|
1991
|
+
};
|
|
1992
|
+
|
|
1993
|
+
// src/api/handlers/ptClaimHandler.ts
|
|
1994
|
+
var PTClaimError = class extends Error {
|
|
1995
|
+
constructor(code, message, details) {
|
|
1996
|
+
super(message);
|
|
1997
|
+
this.code = code;
|
|
1998
|
+
this.details = details;
|
|
1999
|
+
this.name = "PTClaimError";
|
|
2000
|
+
}
|
|
2001
|
+
code;
|
|
2002
|
+
details;
|
|
2003
|
+
};
|
|
2004
|
+
var DEFAULT_LOCK_MS = 15 * 60 * 1e3;
|
|
2005
|
+
var DEFAULT_SIG_DEADLINE_SEC2 = 15 * 60;
|
|
2006
|
+
var PTClaimHandler = class {
|
|
2007
|
+
cfg;
|
|
2008
|
+
constructor(config) {
|
|
2009
|
+
this.cfg = {
|
|
2010
|
+
...config,
|
|
2011
|
+
lockDurationMs: config.lockDurationMs ?? DEFAULT_LOCK_MS,
|
|
2012
|
+
signatureDeadlineSeconds: config.signatureDeadlineSeconds ?? DEFAULT_SIG_DEADLINE_SEC2,
|
|
2013
|
+
now: config.now ?? (() => Date.now())
|
|
2014
|
+
};
|
|
2015
|
+
}
|
|
2016
|
+
async handle(request) {
|
|
2017
|
+
if (getAddress8(request.authenticatedAddress) !== getAddress8(request.userAddress)) {
|
|
2018
|
+
throw new PTClaimError(
|
|
2019
|
+
"VALIDATION_FAILED",
|
|
2020
|
+
`userAddress (${request.userAddress}) does not match authenticated session (${request.authenticatedAddress})`
|
|
2021
|
+
);
|
|
2022
|
+
}
|
|
2023
|
+
if (request.amount <= 0n) {
|
|
2024
|
+
throw new PTClaimError("INVALID_AMOUNT", "claim amount must be positive");
|
|
2025
|
+
}
|
|
2026
|
+
if (this.cfg.issuerStateValidator) {
|
|
2027
|
+
try {
|
|
2028
|
+
await this.cfg.issuerStateValidator.preValidateMint(
|
|
2029
|
+
request.pointTokenAddress,
|
|
2030
|
+
request.amount
|
|
2031
|
+
);
|
|
2032
|
+
} catch (err) {
|
|
2033
|
+
if (err instanceof IssuerStateError) throw err;
|
|
2034
|
+
throw new PTClaimError(
|
|
2035
|
+
"VALIDATION_FAILED",
|
|
2036
|
+
`issuer-state pre-validate failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2037
|
+
);
|
|
2038
|
+
}
|
|
2039
|
+
}
|
|
2040
|
+
const { batchExecutor: batchExecutorAddress } = getContractAddresses2(
|
|
2041
|
+
request.chainId
|
|
2042
|
+
);
|
|
2043
|
+
const lockId = await this.cfg.ledger.lockForMinting(
|
|
2044
|
+
request.userAddress,
|
|
2045
|
+
request.amount,
|
|
2046
|
+
this.cfg.lockDurationMs,
|
|
2047
|
+
request.pointTokenAddress
|
|
2048
|
+
);
|
|
2049
|
+
const signatureDeadline = BigInt(
|
|
2050
|
+
Math.floor(this.cfg.now() / 1e3) + this.cfg.signatureDeadlineSeconds
|
|
2051
|
+
);
|
|
2052
|
+
const feeAmount = this.cfg.feeService ? await this.cfg.feeService.estimateGasFee() : 0n;
|
|
2053
|
+
const domain = {
|
|
2054
|
+
name: this.cfg.pointTokenDomainName,
|
|
2055
|
+
chainId: request.chainId,
|
|
2056
|
+
verifyingContract: request.pointTokenAddress
|
|
2057
|
+
};
|
|
2058
|
+
let userOp;
|
|
2059
|
+
try {
|
|
2060
|
+
userOp = await this.cfg.relayService.prepareMint({
|
|
2061
|
+
userAddress: request.userAddress,
|
|
2062
|
+
aaNonce: request.aaNonce,
|
|
2063
|
+
batchExecutorAddress,
|
|
2064
|
+
pointTokenAddress: request.pointTokenAddress,
|
|
2065
|
+
amount: request.amount,
|
|
2066
|
+
issuerSignerWallet: this.cfg.issuerSignerWallet,
|
|
2067
|
+
domain,
|
|
2068
|
+
mintRequestNonce: request.mintRequestNonce,
|
|
2069
|
+
deadline: signatureDeadline
|
|
2070
|
+
// No feeAmount/feeRecipient — RelayService auto-resolves.
|
|
2071
|
+
});
|
|
2072
|
+
} catch (err) {
|
|
2073
|
+
throw new PTClaimError(
|
|
2074
|
+
"BUILD_FAILED",
|
|
2075
|
+
`prepareMint failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2076
|
+
);
|
|
2077
|
+
}
|
|
2078
|
+
let fallback;
|
|
2079
|
+
if (feeAmount > 0n) {
|
|
2080
|
+
try {
|
|
2081
|
+
fallback = await this.cfg.relayService.prepareMint({
|
|
2082
|
+
userAddress: request.userAddress,
|
|
2083
|
+
aaNonce: request.aaNonce,
|
|
2084
|
+
batchExecutorAddress,
|
|
2085
|
+
pointTokenAddress: request.pointTokenAddress,
|
|
2086
|
+
amount: request.amount,
|
|
2087
|
+
issuerSignerWallet: this.cfg.issuerSignerWallet,
|
|
2088
|
+
domain,
|
|
2089
|
+
mintRequestNonce: request.mintRequestNonce,
|
|
2090
|
+
deadline: signatureDeadline,
|
|
2091
|
+
feeAmount: 0n
|
|
2092
|
+
});
|
|
2093
|
+
} catch (err) {
|
|
2094
|
+
throw new PTClaimError(
|
|
2095
|
+
"BUILD_FAILED",
|
|
2096
|
+
`prepareMint (fallback) failed: ${err instanceof Error ? err.message : String(err)}`
|
|
2097
|
+
);
|
|
2098
|
+
}
|
|
2099
|
+
}
|
|
2100
|
+
const calls = decodeBatchExecuteCalls(userOp.callData);
|
|
2101
|
+
const callsFallback = fallback ? decodeBatchExecuteCalls(fallback.callData) : void 0;
|
|
2102
|
+
return {
|
|
2103
|
+
userOp,
|
|
2104
|
+
fallback,
|
|
2105
|
+
lockId,
|
|
2106
|
+
feeAmount,
|
|
2107
|
+
signatureDeadline,
|
|
2108
|
+
expiresInSeconds: Math.floor(this.cfg.lockDurationMs / 1e3),
|
|
2109
|
+
calls,
|
|
2110
|
+
callsFallback
|
|
2111
|
+
};
|
|
2112
|
+
}
|
|
2113
|
+
};
|
|
2114
|
+
|
|
2115
|
+
// src/api/handlers/swapHandler.ts
|
|
2116
|
+
import {
|
|
2117
|
+
buildSwapWithGasDeduction,
|
|
2118
|
+
decodeBatchExecuteCalls as decodeBatchExecuteCalls2,
|
|
2119
|
+
findBestQuote,
|
|
2120
|
+
getContractAddresses as getContractAddresses3
|
|
2121
|
+
} from "@pafi-dev/core";
|
|
2122
|
+
var SwapError = class extends Error {
|
|
2123
|
+
constructor(code, message) {
|
|
2124
|
+
super(message);
|
|
2125
|
+
this.code = code;
|
|
2126
|
+
this.name = "SwapError";
|
|
2127
|
+
}
|
|
2128
|
+
code;
|
|
2129
|
+
};
|
|
2130
|
+
var DEFAULT_SLIPPAGE_BPS = 50;
|
|
2131
|
+
var DEFAULT_SWAP_DEADLINE_SEC = 5 * 60;
|
|
2132
|
+
var SwapHandler = class {
|
|
2133
|
+
cfg;
|
|
2134
|
+
constructor(config) {
|
|
2135
|
+
this.cfg = {
|
|
2136
|
+
...config,
|
|
2137
|
+
defaultSlippageBps: config.defaultSlippageBps ?? DEFAULT_SLIPPAGE_BPS,
|
|
2138
|
+
defaultSwapDeadlineSeconds: config.defaultSwapDeadlineSeconds ?? DEFAULT_SWAP_DEADLINE_SEC,
|
|
2139
|
+
now: config.now ?? (() => Date.now())
|
|
2140
|
+
};
|
|
2141
|
+
}
|
|
2142
|
+
async handle(request) {
|
|
2143
|
+
if (request.amountIn <= 0n) {
|
|
2144
|
+
throw new SwapError("INVALID_AMOUNT", "amountIn must be positive");
|
|
2145
|
+
}
|
|
2146
|
+
const slippageBps = request.slippageBps ?? this.cfg.defaultSlippageBps;
|
|
2147
|
+
const { usdt, pafiFeeRecipient, universalRouter } = getContractAddresses3(
|
|
2148
|
+
request.chainId
|
|
2149
|
+
);
|
|
2150
|
+
const poolsResponse = await this.cfg.poolsProvider({
|
|
2151
|
+
chainId: request.chainId,
|
|
2152
|
+
pointTokenAddress: request.pointTokenAddress
|
|
2153
|
+
});
|
|
2154
|
+
if (poolsResponse.pools.length === 0) {
|
|
2155
|
+
throw new SwapError(
|
|
2156
|
+
"QUOTE_UNAVAILABLE",
|
|
2157
|
+
"no liquidity pool found for this point token"
|
|
2158
|
+
);
|
|
2159
|
+
}
|
|
2160
|
+
let fallbackQuote;
|
|
2161
|
+
try {
|
|
2162
|
+
fallbackQuote = await findBestQuote(
|
|
2163
|
+
this.cfg.provider,
|
|
2164
|
+
request.chainId,
|
|
2165
|
+
request.pointTokenAddress,
|
|
2166
|
+
usdt,
|
|
2167
|
+
request.amountIn,
|
|
2168
|
+
poolsResponse.pools
|
|
2169
|
+
);
|
|
2170
|
+
} catch {
|
|
2171
|
+
throw new SwapError(
|
|
2172
|
+
"QUOTE_UNAVAILABLE",
|
|
2173
|
+
"no swap path found for this point token"
|
|
2174
|
+
);
|
|
2175
|
+
}
|
|
2176
|
+
const estimatedUsdtOutFallback = fallbackQuote.bestRoute.amountOut;
|
|
2177
|
+
const minAmountOutFallback = estimatedUsdtOutFallback * BigInt(1e4 - slippageBps) / 10000n;
|
|
2178
|
+
const deadline = request.deadline ?? BigInt(
|
|
2179
|
+
Math.floor(this.cfg.now() / 1e3) + this.cfg.defaultSwapDeadlineSeconds
|
|
2180
|
+
);
|
|
2181
|
+
const feeAmount = this.cfg.feeService ? await this.cfg.feeService.estimateGasFee() : 0n;
|
|
2182
|
+
if (feeAmount > 0n && feeAmount >= request.amountIn) {
|
|
2183
|
+
throw new SwapError(
|
|
2184
|
+
"FEE_EXCEEDS_AMOUNT",
|
|
2185
|
+
`gas fee (${feeAmount}) must be strictly less than swap amount (${request.amountIn})`
|
|
2186
|
+
);
|
|
2187
|
+
}
|
|
2188
|
+
const sponsoredAmountIn = request.amountIn - feeAmount;
|
|
2189
|
+
let estimatedUsdtOutSponsored = estimatedUsdtOutFallback;
|
|
2190
|
+
let sponsoredPath = fallbackQuote.bestRoute.path;
|
|
2191
|
+
if (feeAmount > 0n) {
|
|
2192
|
+
try {
|
|
2193
|
+
const sponsoredQuote = await findBestQuote(
|
|
2194
|
+
this.cfg.provider,
|
|
2195
|
+
request.chainId,
|
|
2196
|
+
request.pointTokenAddress,
|
|
2197
|
+
usdt,
|
|
2198
|
+
sponsoredAmountIn,
|
|
2199
|
+
poolsResponse.pools
|
|
2200
|
+
);
|
|
2201
|
+
estimatedUsdtOutSponsored = sponsoredQuote.bestRoute.amountOut;
|
|
2202
|
+
sponsoredPath = sponsoredQuote.bestRoute.path;
|
|
2203
|
+
} catch {
|
|
2204
|
+
throw new SwapError(
|
|
2205
|
+
"QUOTE_UNAVAILABLE",
|
|
2206
|
+
"no swap path found for sponsored amount (after fee deduction)"
|
|
2207
|
+
);
|
|
2208
|
+
}
|
|
2209
|
+
}
|
|
2210
|
+
const minAmountOutSponsored = estimatedUsdtOutSponsored * BigInt(1e4 - slippageBps) / 10000n;
|
|
2211
|
+
const sponsoredOp = buildSwapWithGasDeduction({
|
|
2212
|
+
userAddress: request.userAddress,
|
|
2213
|
+
aaNonce: request.aaNonce,
|
|
2214
|
+
pointTokenAddress: request.pointTokenAddress,
|
|
2215
|
+
outputTokenAddress: usdt,
|
|
2216
|
+
universalRouterAddress: universalRouter,
|
|
2217
|
+
amountIn: sponsoredAmountIn,
|
|
2218
|
+
minAmountOut: minAmountOutSponsored,
|
|
2219
|
+
swapPath: sponsoredPath,
|
|
2220
|
+
deadline,
|
|
2221
|
+
gasFeePt: feeAmount,
|
|
2222
|
+
feeRecipient: pafiFeeRecipient
|
|
2223
|
+
});
|
|
2224
|
+
const fallbackOp = feeAmount > 0n ? buildSwapWithGasDeduction({
|
|
2225
|
+
userAddress: request.userAddress,
|
|
2226
|
+
aaNonce: request.aaNonce,
|
|
2227
|
+
pointTokenAddress: request.pointTokenAddress,
|
|
2228
|
+
outputTokenAddress: usdt,
|
|
2229
|
+
universalRouterAddress: universalRouter,
|
|
2230
|
+
amountIn: request.amountIn,
|
|
2231
|
+
minAmountOut: minAmountOutFallback,
|
|
2232
|
+
swapPath: fallbackQuote.bestRoute.path,
|
|
2233
|
+
deadline,
|
|
2234
|
+
gasFeePt: 0n,
|
|
2235
|
+
feeRecipient: pafiFeeRecipient
|
|
2236
|
+
}) : void 0;
|
|
2237
|
+
return {
|
|
2238
|
+
userOp: sponsoredOp,
|
|
2239
|
+
fallback: fallbackOp,
|
|
2240
|
+
feeAmount,
|
|
2241
|
+
estimatedUsdtOut: estimatedUsdtOutSponsored,
|
|
2242
|
+
minAmountOut: minAmountOutSponsored,
|
|
2243
|
+
estimatedUsdtOutFallback: fallbackOp ? estimatedUsdtOutFallback : void 0,
|
|
2244
|
+
minAmountOutFallback: fallbackOp ? minAmountOutFallback : void 0,
|
|
2245
|
+
deadline,
|
|
2246
|
+
calls: decodeBatchExecuteCalls2(sponsoredOp.callData),
|
|
2247
|
+
callsFallback: fallbackOp ? decodeBatchExecuteCalls2(fallbackOp.callData) : void 0
|
|
2248
|
+
};
|
|
2249
|
+
}
|
|
2250
|
+
};
|
|
2251
|
+
|
|
2252
|
+
// src/api/handlers/perpDepositHandler.ts
|
|
2253
|
+
import {
|
|
2254
|
+
BROKER_HASHES,
|
|
2255
|
+
ORDERLY_RELAY_ABI,
|
|
2256
|
+
ORDERLY_VAULT_ABI,
|
|
2257
|
+
ORDERLY_VAULT_ADDRESSES,
|
|
2258
|
+
TOKEN_HASHES,
|
|
2259
|
+
buildPerpDepositViaRelay,
|
|
2260
|
+
computeAccountId,
|
|
2261
|
+
decodeBatchExecuteCalls as decodeBatchExecuteCalls3,
|
|
2262
|
+
getContractAddresses as getContractAddresses4
|
|
2263
|
+
} from "@pafi-dev/core";
|
|
2264
|
+
var PerpDepositError = class extends Error {
|
|
2265
|
+
constructor(code, message) {
|
|
2266
|
+
super(message);
|
|
2267
|
+
this.code = code;
|
|
2268
|
+
this.name = "PerpDepositError";
|
|
2269
|
+
}
|
|
2270
|
+
code;
|
|
2271
|
+
};
|
|
2272
|
+
var DEFAULT_MAX_FEE_PREMIUM_BPS = 5e3;
|
|
2273
|
+
var PerpDepositHandler = class {
|
|
2274
|
+
cfg;
|
|
2275
|
+
constructor(config) {
|
|
2276
|
+
this.cfg = {
|
|
2277
|
+
...config,
|
|
2278
|
+
maxFeePremiumBps: config.maxFeePremiumBps ?? DEFAULT_MAX_FEE_PREMIUM_BPS
|
|
2279
|
+
};
|
|
2280
|
+
}
|
|
2281
|
+
async handle(request) {
|
|
2282
|
+
if (request.amount <= 0n) {
|
|
2283
|
+
throw new PerpDepositError("INVALID_AMOUNT", "amount must be positive");
|
|
2284
|
+
}
|
|
2285
|
+
const brokerHash = BROKER_HASHES[request.brokerId];
|
|
2286
|
+
const tokenHash = TOKEN_HASHES.USDC;
|
|
2287
|
+
const vault = ORDERLY_VAULT_ADDRESSES[request.chainId];
|
|
2288
|
+
if (!vault) {
|
|
2289
|
+
throw new PerpDepositError(
|
|
2290
|
+
"PERP_DEPOSIT_UNAVAILABLE",
|
|
2291
|
+
`no Orderly Vault for chainId ${request.chainId}`
|
|
2292
|
+
);
|
|
2293
|
+
}
|
|
2294
|
+
const { orderlyRelay: relayAddress, pafiFeeRecipient } = getContractAddresses4(request.chainId);
|
|
2295
|
+
const [usdcAddress, brokerAllowed] = await Promise.all([
|
|
2296
|
+
this.cfg.provider.readContract({
|
|
2297
|
+
address: vault,
|
|
2298
|
+
abi: ORDERLY_VAULT_ABI,
|
|
2299
|
+
functionName: "getAllowedToken",
|
|
2300
|
+
args: [tokenHash]
|
|
2301
|
+
}),
|
|
2302
|
+
this.cfg.provider.readContract({
|
|
2303
|
+
address: vault,
|
|
2304
|
+
abi: ORDERLY_VAULT_ABI,
|
|
2305
|
+
functionName: "getAllowedBroker",
|
|
2306
|
+
args: [brokerHash]
|
|
2307
|
+
})
|
|
2308
|
+
]);
|
|
2309
|
+
if (!brokerAllowed) {
|
|
2310
|
+
throw new PerpDepositError(
|
|
2311
|
+
"BROKER_NOT_WHITELISTED",
|
|
2312
|
+
`broker "${request.brokerId}" is not whitelisted on Orderly Vault`
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
const accountId = computeAccountId(request.userAddress, brokerHash);
|
|
2316
|
+
const requestForQuote = {
|
|
2317
|
+
token: usdcAddress,
|
|
2318
|
+
receiver: request.userAddress,
|
|
2319
|
+
brokerHash,
|
|
2320
|
+
totalAmount: request.amount,
|
|
2321
|
+
maxFee: 0n
|
|
2322
|
+
};
|
|
2323
|
+
const [relayTokenFee, ptGasFee] = await Promise.all([
|
|
2324
|
+
this.cfg.provider.readContract({
|
|
2325
|
+
address: relayAddress,
|
|
2326
|
+
abi: ORDERLY_RELAY_ABI,
|
|
2327
|
+
functionName: "quoteTokenFee",
|
|
2328
|
+
args: [requestForQuote]
|
|
2329
|
+
}),
|
|
2330
|
+
this.cfg.feeService ? this.cfg.feeService.estimateGasFee() : Promise.resolve(0n)
|
|
2331
|
+
]);
|
|
2332
|
+
if (relayTokenFee >= request.amount) {
|
|
2333
|
+
throw new PerpDepositError(
|
|
2334
|
+
"RELAY_FEE_EXCEEDS_AMOUNT",
|
|
2335
|
+
`Relay quoted fee ${relayTokenFee} >= deposit amount ${request.amount}`
|
|
2336
|
+
);
|
|
2337
|
+
}
|
|
2338
|
+
const maxFee = relayTokenFee * BigInt(1e4 + this.cfg.maxFeePremiumBps) / 10000n;
|
|
2339
|
+
const depositReq = {
|
|
2340
|
+
token: usdcAddress,
|
|
2341
|
+
receiver: request.userAddress,
|
|
2342
|
+
brokerHash,
|
|
2343
|
+
totalAmount: request.amount,
|
|
2344
|
+
maxFee
|
|
2345
|
+
};
|
|
2346
|
+
const sponsoredOp = buildPerpDepositViaRelay({
|
|
2347
|
+
userAddress: request.userAddress,
|
|
2348
|
+
aaNonce: request.aaNonce,
|
|
2349
|
+
relayAddress,
|
|
2350
|
+
request: depositReq,
|
|
2351
|
+
pointTokenAddress: this.cfg.pointTokenAddress,
|
|
2352
|
+
gasFeePt: ptGasFee,
|
|
2353
|
+
gasFeePtRecipient: pafiFeeRecipient
|
|
2354
|
+
});
|
|
2355
|
+
const fallbackOp = ptGasFee > 0n ? buildPerpDepositViaRelay({
|
|
2356
|
+
userAddress: request.userAddress,
|
|
2357
|
+
aaNonce: request.aaNonce,
|
|
2358
|
+
relayAddress,
|
|
2359
|
+
request: depositReq
|
|
2360
|
+
}) : void 0;
|
|
2361
|
+
return {
|
|
2362
|
+
userOp: sponsoredOp,
|
|
2363
|
+
fallback: fallbackOp,
|
|
2364
|
+
feeAmount: ptGasFee,
|
|
2365
|
+
relayTokenFee,
|
|
2366
|
+
maxFee,
|
|
2367
|
+
netDeposit: request.amount - relayTokenFee,
|
|
2368
|
+
accountId,
|
|
2369
|
+
brokerHash,
|
|
2370
|
+
usdcAddress,
|
|
2371
|
+
relayAddress,
|
|
2372
|
+
calls: decodeBatchExecuteCalls3(sponsoredOp.callData),
|
|
2373
|
+
callsFallback: fallbackOp ? decodeBatchExecuteCalls3(fallbackOp.callData) : void 0
|
|
2374
|
+
};
|
|
2375
|
+
}
|
|
2376
|
+
};
|
|
2377
|
+
|
|
1701
2378
|
// src/pools/subgraphPoolsProvider.ts
|
|
1702
2379
|
import { isAddress } from "viem";
|
|
1703
2380
|
import { PAFI_SUBGRAPH_URL } from "@pafi-dev/core";
|
|
@@ -2316,8 +2993,8 @@ var PafiBackendClient = class {
|
|
|
2316
2993
|
};
|
|
2317
2994
|
|
|
2318
2995
|
// src/config.ts
|
|
2319
|
-
import { getAddress as
|
|
2320
|
-
import { getContractAddresses as
|
|
2996
|
+
import { getAddress as getAddress9 } from "viem";
|
|
2997
|
+
import { getContractAddresses as getContractAddresses5 } from "@pafi-dev/core";
|
|
2321
2998
|
function createIssuerService(config) {
|
|
2322
2999
|
if (!config.provider) {
|
|
2323
3000
|
throw new Error("createIssuerService: provider is required");
|
|
@@ -2337,7 +3014,7 @@ function createIssuerService(config) {
|
|
|
2337
3014
|
"createIssuerService: at least one of pointTokenAddress / pointTokenAddresses is required"
|
|
2338
3015
|
);
|
|
2339
3016
|
}
|
|
2340
|
-
const tokenAddresses = rawAddresses.map((a) =>
|
|
3017
|
+
const tokenAddresses = rawAddresses.map((a) => getAddress9(a));
|
|
2341
3018
|
const ledger = config.ledger;
|
|
2342
3019
|
const sessionStore = config.sessionStore ?? new MemorySessionStore();
|
|
2343
3020
|
const policy = config.policy ?? new DefaultPolicyEngine({ ledger });
|
|
@@ -2387,7 +3064,7 @@ function createIssuerService(config) {
|
|
|
2387
3064
|
indexers.set(tokenAddress, new PointIndexer(indexerConfig));
|
|
2388
3065
|
}
|
|
2389
3066
|
const firstIndexer = indexers.get(tokenAddresses[0]);
|
|
2390
|
-
const chainAddresses =
|
|
3067
|
+
const chainAddresses = getContractAddresses5(config.chainId);
|
|
2391
3068
|
const resolvedContracts = {
|
|
2392
3069
|
batchExecutor: chainAddresses.batchExecutor,
|
|
2393
3070
|
usdt: chainAddresses.usdt,
|
|
@@ -2434,163 +3111,13 @@ function createIssuerService(config) {
|
|
|
2434
3111
|
};
|
|
2435
3112
|
}
|
|
2436
3113
|
|
|
2437
|
-
// src/userop-store/serialize.ts
|
|
2438
|
-
import { serializeUserOpToJsonRpc } from "@pafi-dev/core";
|
|
2439
|
-
function serializeEntryToJsonRpc(entry, signature, variant = "sponsored") {
|
|
2440
|
-
if (variant === "fallback") {
|
|
2441
|
-
if (!entry.fallback) {
|
|
2442
|
-
throw new Error(
|
|
2443
|
-
"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."
|
|
2444
|
-
);
|
|
2445
|
-
}
|
|
2446
|
-
return serializeUserOpToJsonRpc(
|
|
2447
|
-
{
|
|
2448
|
-
sender: entry.sender,
|
|
2449
|
-
nonce: BigInt(entry.nonce),
|
|
2450
|
-
callData: entry.fallback.callData,
|
|
2451
|
-
callGasLimit: BigInt(entry.fallback.callGasLimit),
|
|
2452
|
-
verificationGasLimit: BigInt(entry.fallback.verificationGasLimit),
|
|
2453
|
-
preVerificationGas: BigInt(entry.fallback.preVerificationGas),
|
|
2454
|
-
maxFeePerGas: BigInt(entry.maxFeePerGas),
|
|
2455
|
-
maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas)
|
|
2456
|
-
// intentionally no paymaster — user pays ETH gas
|
|
2457
|
-
},
|
|
2458
|
-
signature
|
|
2459
|
-
);
|
|
2460
|
-
}
|
|
2461
|
-
return serializeUserOpToJsonRpc(
|
|
2462
|
-
{
|
|
2463
|
-
sender: entry.sender,
|
|
2464
|
-
nonce: BigInt(entry.nonce),
|
|
2465
|
-
callData: entry.callData,
|
|
2466
|
-
callGasLimit: BigInt(entry.callGasLimit),
|
|
2467
|
-
verificationGasLimit: BigInt(entry.verificationGasLimit),
|
|
2468
|
-
preVerificationGas: BigInt(entry.preVerificationGas),
|
|
2469
|
-
maxFeePerGas: BigInt(entry.maxFeePerGas),
|
|
2470
|
-
maxPriorityFeePerGas: BigInt(entry.maxPriorityFeePerGas),
|
|
2471
|
-
paymaster: entry.paymaster,
|
|
2472
|
-
paymasterVerificationGasLimit: entry.paymasterVerificationGasLimit != null ? BigInt(entry.paymasterVerificationGasLimit) : void 0,
|
|
2473
|
-
paymasterPostOpGasLimit: entry.paymasterPostOpGasLimit != null ? BigInt(entry.paymasterPostOpGasLimit) : void 0,
|
|
2474
|
-
paymasterData: entry.paymasterData
|
|
2475
|
-
},
|
|
2476
|
-
signature
|
|
2477
|
-
);
|
|
2478
|
-
}
|
|
2479
|
-
|
|
2480
|
-
// src/userop-store/prepareUserOp.ts
|
|
2481
|
-
import {
|
|
2482
|
-
buildUserOpTypedData,
|
|
2483
|
-
computeUserOpHash
|
|
2484
|
-
} from "@pafi-dev/core";
|
|
2485
|
-
function serializeUserOpTypedData(td) {
|
|
2486
|
-
return {
|
|
2487
|
-
domain: td.domain,
|
|
2488
|
-
types: td.types,
|
|
2489
|
-
primaryType: td.primaryType,
|
|
2490
|
-
message: {
|
|
2491
|
-
sender: td.message.sender,
|
|
2492
|
-
nonce: `0x${td.message.nonce.toString(16)}`,
|
|
2493
|
-
initCode: td.message.initCode,
|
|
2494
|
-
callData: td.message.callData,
|
|
2495
|
-
accountGasLimits: td.message.accountGasLimits,
|
|
2496
|
-
preVerificationGas: `0x${td.message.preVerificationGas.toString(
|
|
2497
|
-
16
|
|
2498
|
-
)}`,
|
|
2499
|
-
gasFees: td.message.gasFees,
|
|
2500
|
-
paymasterAndData: td.message.paymasterAndData
|
|
2501
|
-
}
|
|
2502
|
-
};
|
|
2503
|
-
}
|
|
2504
|
-
function mergePaymasterFields(userOp, paymasterFields) {
|
|
2505
|
-
if (!paymasterFields) return userOp;
|
|
2506
|
-
const merged = {
|
|
2507
|
-
...userOp
|
|
2508
|
-
};
|
|
2509
|
-
for (const [k, v] of Object.entries(paymasterFields)) {
|
|
2510
|
-
if (v !== void 0) merged[k] = v;
|
|
2511
|
-
}
|
|
2512
|
-
return merged;
|
|
2513
|
-
}
|
|
2514
|
-
async function prepareMobileUserOp(params) {
|
|
2515
|
-
const userOp = mergePaymasterFields(
|
|
2516
|
-
params.partialUserOp,
|
|
2517
|
-
params.paymasterFields
|
|
2518
|
-
);
|
|
2519
|
-
const userOpHash = computeUserOpHash(userOp, params.chainId);
|
|
2520
|
-
const typedData = serializeUserOpTypedData(
|
|
2521
|
-
buildUserOpTypedData(userOp, params.chainId)
|
|
2522
|
-
);
|
|
2523
|
-
let fallback;
|
|
2524
|
-
let fallbackEntry;
|
|
2525
|
-
if (params.partialUserOpFallback) {
|
|
2526
|
-
const fallbackUserOp = {
|
|
2527
|
-
...params.partialUserOpFallback,
|
|
2528
|
-
maxFeePerGas: userOp.maxFeePerGas,
|
|
2529
|
-
maxPriorityFeePerGas: userOp.maxPriorityFeePerGas
|
|
2530
|
-
};
|
|
2531
|
-
const fallbackHash = computeUserOpHash(fallbackUserOp, params.chainId);
|
|
2532
|
-
const fallbackTypedData = serializeUserOpTypedData(
|
|
2533
|
-
buildUserOpTypedData(fallbackUserOp, params.chainId)
|
|
2534
|
-
);
|
|
2535
|
-
fallback = {
|
|
2536
|
-
userOp: fallbackUserOp,
|
|
2537
|
-
userOpHash: fallbackHash,
|
|
2538
|
-
typedData: fallbackTypedData
|
|
2539
|
-
};
|
|
2540
|
-
fallbackEntry = {
|
|
2541
|
-
callData: fallbackUserOp.callData,
|
|
2542
|
-
callGasLimit: fallbackUserOp.callGasLimit.toString(),
|
|
2543
|
-
verificationGasLimit: fallbackUserOp.verificationGasLimit.toString(),
|
|
2544
|
-
preVerificationGas: fallbackUserOp.preVerificationGas.toString(),
|
|
2545
|
-
userOpHash: fallbackHash
|
|
2546
|
-
};
|
|
2547
|
-
}
|
|
2548
|
-
const entry = {
|
|
2549
|
-
sender: userOp.sender,
|
|
2550
|
-
nonce: userOp.nonce.toString(),
|
|
2551
|
-
callData: userOp.callData,
|
|
2552
|
-
callGasLimit: userOp.callGasLimit.toString(),
|
|
2553
|
-
verificationGasLimit: userOp.verificationGasLimit.toString(),
|
|
2554
|
-
preVerificationGas: userOp.preVerificationGas.toString(),
|
|
2555
|
-
maxFeePerGas: userOp.maxFeePerGas.toString(),
|
|
2556
|
-
maxPriorityFeePerGas: userOp.maxPriorityFeePerGas.toString(),
|
|
2557
|
-
paymaster: userOp.paymaster,
|
|
2558
|
-
paymasterVerificationGasLimit: userOp.paymasterVerificationGasLimit?.toString(),
|
|
2559
|
-
paymasterPostOpGasLimit: userOp.paymasterPostOpGasLimit?.toString(),
|
|
2560
|
-
paymasterData: userOp.paymasterData,
|
|
2561
|
-
chainId: params.chainId,
|
|
2562
|
-
userOpHash,
|
|
2563
|
-
fallback: fallbackEntry
|
|
2564
|
-
};
|
|
2565
|
-
await params.store.save(params.lockId, entry, params.ttlSeconds);
|
|
2566
|
-
return {
|
|
2567
|
-
sponsored: { userOp, userOpHash, typedData },
|
|
2568
|
-
fallback,
|
|
2569
|
-
entry
|
|
2570
|
-
};
|
|
2571
|
-
}
|
|
2572
|
-
|
|
2573
3114
|
// src/issuer-state/validator.ts
|
|
2574
|
-
import { getAddress as
|
|
3115
|
+
import { getAddress as getAddress10 } from "viem";
|
|
2575
3116
|
import {
|
|
2576
3117
|
POINT_TOKEN_V2_ABI as POINT_TOKEN_V2_ABI3,
|
|
2577
3118
|
issuerRegistryGetIssuerFlatAbi,
|
|
2578
|
-
getContractAddresses as
|
|
3119
|
+
getContractAddresses as getContractAddresses6
|
|
2579
3120
|
} from "@pafi-dev/core";
|
|
2580
|
-
|
|
2581
|
-
// src/issuer-state/types.ts
|
|
2582
|
-
var IssuerStateError = class extends Error {
|
|
2583
|
-
constructor(code, message, details) {
|
|
2584
|
-
super(message);
|
|
2585
|
-
this.code = code;
|
|
2586
|
-
this.details = details;
|
|
2587
|
-
this.name = "IssuerStateError";
|
|
2588
|
-
}
|
|
2589
|
-
code;
|
|
2590
|
-
details;
|
|
2591
|
-
};
|
|
2592
|
-
|
|
2593
|
-
// src/issuer-state/validator.ts
|
|
2594
3121
|
var ISSUER_RECORD_TTL_MS = 3e4;
|
|
2595
3122
|
var IssuerStateValidator = class _IssuerStateValidator {
|
|
2596
3123
|
constructor(provider, registryAddress) {
|
|
@@ -2607,7 +3134,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2607
3134
|
* `CONTRACT_ADDRESSES` map for the given chain.
|
|
2608
3135
|
*/
|
|
2609
3136
|
static forChain(provider, chainId) {
|
|
2610
|
-
const { issuerRegistry } =
|
|
3137
|
+
const { issuerRegistry } = getContractAddresses6(chainId);
|
|
2611
3138
|
return new _IssuerStateValidator(provider, issuerRegistry);
|
|
2612
3139
|
}
|
|
2613
3140
|
/**
|
|
@@ -2616,7 +3143,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2616
3143
|
*/
|
|
2617
3144
|
invalidate(pointToken) {
|
|
2618
3145
|
if (pointToken) {
|
|
2619
|
-
const key =
|
|
3146
|
+
const key = getAddress10(pointToken);
|
|
2620
3147
|
this.pointTokenIssuerCache.delete(key);
|
|
2621
3148
|
this.stateCache.delete(key);
|
|
2622
3149
|
this.inflight.delete(key);
|
|
@@ -2631,7 +3158,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2631
3158
|
* The issuer field is set at `initialize()` and never changes.
|
|
2632
3159
|
*/
|
|
2633
3160
|
async getIssuerAddressForPointToken(pointToken) {
|
|
2634
|
-
const key =
|
|
3161
|
+
const key = getAddress10(pointToken);
|
|
2635
3162
|
const cached = this.pointTokenIssuerCache.get(key);
|
|
2636
3163
|
if (cached) return cached;
|
|
2637
3164
|
const issuer = await this.provider.readContract({
|
|
@@ -2639,15 +3166,15 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2639
3166
|
abi: POINT_TOKEN_V2_ABI3,
|
|
2640
3167
|
functionName: "issuer"
|
|
2641
3168
|
});
|
|
2642
|
-
this.pointTokenIssuerCache.set(key,
|
|
2643
|
-
return
|
|
3169
|
+
this.pointTokenIssuerCache.set(key, getAddress10(issuer));
|
|
3170
|
+
return getAddress10(issuer);
|
|
2644
3171
|
}
|
|
2645
3172
|
/**
|
|
2646
3173
|
* Read registry record + totalSupply, with 30s cache and in-flight
|
|
2647
3174
|
* deduplication. Does NOT throw on inactive/missing — returns raw state.
|
|
2648
3175
|
*/
|
|
2649
3176
|
async getIssuerState(pointToken) {
|
|
2650
|
-
const tokenAddr =
|
|
3177
|
+
const tokenAddr = getAddress10(pointToken);
|
|
2651
3178
|
const now = Date.now();
|
|
2652
3179
|
const cached = this.stateCache.get(tokenAddr);
|
|
2653
3180
|
if (cached && cached.expiresAt > now) return cached.value;
|
|
@@ -2750,6 +3277,8 @@ export {
|
|
|
2750
3277
|
AuthError,
|
|
2751
3278
|
AuthService,
|
|
2752
3279
|
BalanceAggregator,
|
|
3280
|
+
BundlerNotConfiguredError,
|
|
3281
|
+
BundlerRejectedError,
|
|
2753
3282
|
BurnIndexer,
|
|
2754
3283
|
DefaultPolicyEngine,
|
|
2755
3284
|
FeeManager,
|
|
@@ -2762,13 +3291,20 @@ export {
|
|
|
2762
3291
|
NonceManager,
|
|
2763
3292
|
PAFI_ISSUER_SDK_VERSION,
|
|
2764
3293
|
PAFI_SUBGRAPH_URL,
|
|
3294
|
+
PTClaimError,
|
|
3295
|
+
PTClaimHandler,
|
|
2765
3296
|
PTRedeemError,
|
|
2766
3297
|
PTRedeemHandler,
|
|
2767
3298
|
PafiBackendClient,
|
|
2768
3299
|
PafiBackendError,
|
|
3300
|
+
PendingUserOpNotFoundError,
|
|
3301
|
+
PerpDepositError,
|
|
3302
|
+
PerpDepositHandler,
|
|
2769
3303
|
PointIndexer,
|
|
2770
3304
|
RelayError,
|
|
2771
3305
|
RelayService,
|
|
3306
|
+
SwapError,
|
|
3307
|
+
SwapHandler,
|
|
2772
3308
|
TopUpRedemptionError,
|
|
2773
3309
|
TopUpRedemptionHandler,
|
|
2774
3310
|
authenticateRequest,
|
|
@@ -2777,9 +3313,13 @@ export {
|
|
|
2777
3313
|
createSubgraphNativeUsdtQuoter,
|
|
2778
3314
|
createSubgraphPoolsProvider,
|
|
2779
3315
|
handleClaimStatus,
|
|
3316
|
+
handleMobilePrepare,
|
|
3317
|
+
handleMobileSubmit,
|
|
2780
3318
|
handleRedeemStatus,
|
|
2781
3319
|
mergePaymasterFields,
|
|
2782
3320
|
prepareMobileUserOp,
|
|
3321
|
+
relayUserOp,
|
|
3322
|
+
requestPaymaster,
|
|
2783
3323
|
serializeEntryToJsonRpc,
|
|
2784
3324
|
serializeUserOpTypedData
|
|
2785
3325
|
};
|