@pafi-dev/issuer 0.5.11 → 0.5.12
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 +113 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +43 -1
- package/dist/index.d.ts +43 -1
- package/dist/index.js +104 -12
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -45,6 +45,7 @@ __export(index_exports, {
|
|
|
45
45
|
TopUpRedemptionHandler: () => TopUpRedemptionHandler,
|
|
46
46
|
authenticateRequest: () => authenticateRequest,
|
|
47
47
|
createIssuerService: () => createIssuerService,
|
|
48
|
+
createNativePtQuoter: () => createNativePtQuoter,
|
|
48
49
|
createSubgraphNativeUsdtQuoter: () => createSubgraphNativeUsdtQuoter,
|
|
49
50
|
createSubgraphPoolsProvider: () => createSubgraphPoolsProvider,
|
|
50
51
|
serializeEntryToJsonRpc: () => serializeEntryToJsonRpc
|
|
@@ -1776,6 +1777,107 @@ function toUsdtPerNative(priceFloat, usdtDecimals) {
|
|
|
1776
1777
|
return BigInt(whole + padded);
|
|
1777
1778
|
}
|
|
1778
1779
|
|
|
1780
|
+
// src/pools/nativePtQuoter.ts
|
|
1781
|
+
var import_viem10 = require("viem");
|
|
1782
|
+
var CHAINLINK_ABI = (0, import_viem10.parseAbi)([
|
|
1783
|
+
"function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound)"
|
|
1784
|
+
]);
|
|
1785
|
+
var CHAINLINK_MAX_AGE_S = 3600n;
|
|
1786
|
+
var POOL_PRICE_QUERY = `
|
|
1787
|
+
query GetPoolPrice($id: ID!) {
|
|
1788
|
+
pafiToken(id: $id) {
|
|
1789
|
+
pool {
|
|
1790
|
+
token0 { id }
|
|
1791
|
+
token1 { id }
|
|
1792
|
+
token0Price
|
|
1793
|
+
token1Price
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
`;
|
|
1798
|
+
function createNativePtQuoter(config) {
|
|
1799
|
+
const {
|
|
1800
|
+
provider,
|
|
1801
|
+
pointTokenAddress,
|
|
1802
|
+
chainlinkFeedAddress = "0x71041dddad3595F9CEd3DcCFBe3D1F4b0a16Bb70",
|
|
1803
|
+
subgraphUrl = import_core6.PAFI_SUBGRAPH_URL,
|
|
1804
|
+
cacheTtlMs = 3e4,
|
|
1805
|
+
fallbackEthPriceUsd = 3e3,
|
|
1806
|
+
fallbackPtPriceUsdt = 0.1,
|
|
1807
|
+
fetchImpl = globalThis.fetch,
|
|
1808
|
+
now = () => Date.now()
|
|
1809
|
+
} = config;
|
|
1810
|
+
let ethPriceCache;
|
|
1811
|
+
let ptPriceCache;
|
|
1812
|
+
async function getEthPrice8dec() {
|
|
1813
|
+
const ts = now();
|
|
1814
|
+
if (ethPriceCache && ethPriceCache.expiresAt > ts) return ethPriceCache.value;
|
|
1815
|
+
try {
|
|
1816
|
+
const result = await provider.readContract({
|
|
1817
|
+
address: chainlinkFeedAddress,
|
|
1818
|
+
abi: CHAINLINK_ABI,
|
|
1819
|
+
functionName: "latestRoundData"
|
|
1820
|
+
});
|
|
1821
|
+
const answer = result[1];
|
|
1822
|
+
const updatedAt = result[3];
|
|
1823
|
+
if (answer <= 0n) throw new Error("Chainlink: non-positive price");
|
|
1824
|
+
const ageS = BigInt(Math.floor(ts / 1e3)) - updatedAt;
|
|
1825
|
+
if (ageS > CHAINLINK_MAX_AGE_S) {
|
|
1826
|
+
throw new Error(`Chainlink: price stale by ${ageS}s`);
|
|
1827
|
+
}
|
|
1828
|
+
ethPriceCache = { value: answer, expiresAt: ts + cacheTtlMs };
|
|
1829
|
+
return answer;
|
|
1830
|
+
} catch (err) {
|
|
1831
|
+
console.warn("[nativePtQuoter] Chainlink unavailable, using fallback:", err.message);
|
|
1832
|
+
return BigInt(Math.round(fallbackEthPriceUsd * 1e8));
|
|
1833
|
+
}
|
|
1834
|
+
}
|
|
1835
|
+
async function getPtPerUsdt18dec() {
|
|
1836
|
+
const ts = now();
|
|
1837
|
+
if (ptPriceCache && ptPriceCache.expiresAt > ts) return ptPriceCache.value;
|
|
1838
|
+
try {
|
|
1839
|
+
const response = await fetchImpl(subgraphUrl, {
|
|
1840
|
+
method: "POST",
|
|
1841
|
+
headers: { "Content-Type": "application/json" },
|
|
1842
|
+
body: JSON.stringify({
|
|
1843
|
+
query: POOL_PRICE_QUERY,
|
|
1844
|
+
variables: { id: pointTokenAddress.toLowerCase() }
|
|
1845
|
+
})
|
|
1846
|
+
});
|
|
1847
|
+
if (!response.ok) throw new Error(`subgraph HTTP ${response.status}`);
|
|
1848
|
+
const json = await response.json();
|
|
1849
|
+
if (json.errors?.length) throw new Error(json.errors.map((e) => e.message).join("; "));
|
|
1850
|
+
const pool = json.data?.pafiToken?.pool;
|
|
1851
|
+
if (!pool) throw new Error("pafiToken or pool not found in subgraph");
|
|
1852
|
+
const isPtToken0 = pool.token0.id.toLowerCase() === pointTokenAddress.toLowerCase();
|
|
1853
|
+
const ptPerUsdtStr = isPtToken0 ? pool.token0Price : pool.token1Price;
|
|
1854
|
+
if (!ptPerUsdtStr || Number(ptPerUsdtStr) <= 0) {
|
|
1855
|
+
throw new Error(`invalid PT/USDT price from subgraph: ${ptPerUsdtStr}`);
|
|
1856
|
+
}
|
|
1857
|
+
const value = parseBigDecimalTo18(ptPerUsdtStr);
|
|
1858
|
+
ptPriceCache = { value, expiresAt: ts + cacheTtlMs };
|
|
1859
|
+
return value;
|
|
1860
|
+
} catch (err) {
|
|
1861
|
+
console.warn("[nativePtQuoter] subgraph unavailable, using fallback:", err.message);
|
|
1862
|
+
return parseBigDecimalTo18(fallbackPtPriceUsdt.toString());
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1865
|
+
return async (amountNative) => {
|
|
1866
|
+
if (amountNative === 0n) return 0n;
|
|
1867
|
+
const [ethPrice8dec, ptPerUsdt18dec] = await Promise.all([
|
|
1868
|
+
getEthPrice8dec(),
|
|
1869
|
+
getPtPerUsdt18dec()
|
|
1870
|
+
]);
|
|
1871
|
+
return amountNative * ethPrice8dec * ptPerUsdt18dec / 10n ** 26n;
|
|
1872
|
+
};
|
|
1873
|
+
}
|
|
1874
|
+
function parseBigDecimalTo18(s) {
|
|
1875
|
+
const SCALE = 18;
|
|
1876
|
+
const [whole = "0", frac = ""] = s.split(".");
|
|
1877
|
+
const padded = (frac + "0".repeat(SCALE)).slice(0, SCALE);
|
|
1878
|
+
return BigInt(whole + padded);
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1779
1881
|
// src/balance/balanceAggregator.ts
|
|
1780
1882
|
var import_core7 = require("@pafi-dev/core");
|
|
1781
1883
|
var BalanceAggregator = class {
|
|
@@ -1981,7 +2083,7 @@ var PafiBackendClient = class {
|
|
|
1981
2083
|
};
|
|
1982
2084
|
|
|
1983
2085
|
// src/config.ts
|
|
1984
|
-
var
|
|
2086
|
+
var import_viem11 = require("viem");
|
|
1985
2087
|
var import_core8 = require("@pafi-dev/core");
|
|
1986
2088
|
function createIssuerService(config) {
|
|
1987
2089
|
if (!config.provider) {
|
|
@@ -2002,7 +2104,7 @@ function createIssuerService(config) {
|
|
|
2002
2104
|
"createIssuerService: at least one of pointTokenAddress / pointTokenAddresses is required"
|
|
2003
2105
|
);
|
|
2004
2106
|
}
|
|
2005
|
-
const tokenAddresses = rawAddresses.map((a) => (0,
|
|
2107
|
+
const tokenAddresses = rawAddresses.map((a) => (0, import_viem11.getAddress)(a));
|
|
2006
2108
|
const ledger = config.ledger;
|
|
2007
2109
|
const sessionStore = config.sessionStore ?? new MemorySessionStore();
|
|
2008
2110
|
const policy = config.policy ?? new DefaultPolicyEngine({ ledger });
|
|
@@ -2119,7 +2221,7 @@ function serializeEntryToJsonRpc(entry, signature) {
|
|
|
2119
2221
|
}
|
|
2120
2222
|
|
|
2121
2223
|
// src/issuer-state/validator.ts
|
|
2122
|
-
var
|
|
2224
|
+
var import_viem12 = require("viem");
|
|
2123
2225
|
var import_core10 = require("@pafi-dev/core");
|
|
2124
2226
|
|
|
2125
2227
|
// src/issuer-state/types.ts
|
|
@@ -2160,7 +2262,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2160
2262
|
*/
|
|
2161
2263
|
invalidate(pointToken) {
|
|
2162
2264
|
if (pointToken) {
|
|
2163
|
-
const key = (0,
|
|
2265
|
+
const key = (0, import_viem12.getAddress)(pointToken);
|
|
2164
2266
|
this.pointTokenIssuerCache.delete(key);
|
|
2165
2267
|
this.stateCache.delete(key);
|
|
2166
2268
|
this.inflight.delete(key);
|
|
@@ -2175,7 +2277,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2175
2277
|
* The issuer field is set at `initialize()` and never changes.
|
|
2176
2278
|
*/
|
|
2177
2279
|
async getIssuerAddressForPointToken(pointToken) {
|
|
2178
|
-
const key = (0,
|
|
2280
|
+
const key = (0, import_viem12.getAddress)(pointToken);
|
|
2179
2281
|
const cached = this.pointTokenIssuerCache.get(key);
|
|
2180
2282
|
if (cached) return cached;
|
|
2181
2283
|
const issuer = await this.provider.readContract({
|
|
@@ -2183,15 +2285,15 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2183
2285
|
abi: import_core10.POINT_TOKEN_V2_ABI,
|
|
2184
2286
|
functionName: "issuer"
|
|
2185
2287
|
});
|
|
2186
|
-
this.pointTokenIssuerCache.set(key, (0,
|
|
2187
|
-
return (0,
|
|
2288
|
+
this.pointTokenIssuerCache.set(key, (0, import_viem12.getAddress)(issuer));
|
|
2289
|
+
return (0, import_viem12.getAddress)(issuer);
|
|
2188
2290
|
}
|
|
2189
2291
|
/**
|
|
2190
2292
|
* Read registry record + totalSupply, with 30s cache and in-flight
|
|
2191
2293
|
* deduplication. Does NOT throw on inactive/missing — returns raw state.
|
|
2192
2294
|
*/
|
|
2193
2295
|
async getIssuerState(pointToken) {
|
|
2194
|
-
const tokenAddr = (0,
|
|
2296
|
+
const tokenAddr = (0, import_viem12.getAddress)(pointToken);
|
|
2195
2297
|
const now = Date.now();
|
|
2196
2298
|
const cached = this.stateCache.get(tokenAddr);
|
|
2197
2299
|
if (cached && cached.expiresAt > now) return cached.value;
|
|
@@ -2258,7 +2360,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2258
2360
|
}
|
|
2259
2361
|
async fetchIssuerState(tokenAddr) {
|
|
2260
2362
|
const issuerAddr = await this.getIssuerAddressForPointToken(tokenAddr);
|
|
2261
|
-
const [
|
|
2363
|
+
const [issuerStruct, totalSupply] = await Promise.all([
|
|
2262
2364
|
this.provider.readContract({
|
|
2263
2365
|
address: this.registryAddress,
|
|
2264
2366
|
abi: import_core10.issuerRegistryAbi,
|
|
@@ -2271,17 +2373,7 @@ var IssuerStateValidator = class _IssuerStateValidator {
|
|
|
2271
2373
|
functionName: "totalSupply"
|
|
2272
2374
|
})
|
|
2273
2375
|
]);
|
|
2274
|
-
const issuer =
|
|
2275
|
-
issuerAddress: tuple[0],
|
|
2276
|
-
signerAddress: tuple[1],
|
|
2277
|
-
name: tuple[2],
|
|
2278
|
-
symbol: tuple[3],
|
|
2279
|
-
declaredTotalSupply: tuple[4],
|
|
2280
|
-
capBasisPoints: tuple[5],
|
|
2281
|
-
active: tuple[6],
|
|
2282
|
-
pointToken: tuple[7],
|
|
2283
|
-
mintingOracle: tuple[8]
|
|
2284
|
-
};
|
|
2376
|
+
const issuer = issuerStruct;
|
|
2285
2377
|
const hardCap = issuer.declaredTotalSupply * BigInt(issuer.capBasisPoints) / 10000n;
|
|
2286
2378
|
const remaining = hardCap > totalSupply ? hardCap - totalSupply : 0n;
|
|
2287
2379
|
return { issuer, totalSupply, hardCap, remaining };
|
|
@@ -2317,6 +2409,7 @@ var PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
|
2317
2409
|
TopUpRedemptionHandler,
|
|
2318
2410
|
authenticateRequest,
|
|
2319
2411
|
createIssuerService,
|
|
2412
|
+
createNativePtQuoter,
|
|
2320
2413
|
createSubgraphNativeUsdtQuoter,
|
|
2321
2414
|
createSubgraphPoolsProvider,
|
|
2322
2415
|
serializeEntryToJsonRpc
|