@pafi-dev/issuer 0.5.8 → 0.5.10
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 +174 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +132 -1
- package/dist/index.d.ts +132 -1
- package/dist/index.js +176 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -28,6 +28,8 @@ __export(index_exports, {
|
|
|
28
28
|
FeeManager: () => FeeManager,
|
|
29
29
|
InMemoryCursorStore: () => InMemoryCursorStore,
|
|
30
30
|
IssuerApiHandlers: () => IssuerApiHandlers,
|
|
31
|
+
IssuerStateError: () => IssuerStateError,
|
|
32
|
+
IssuerStateValidator: () => IssuerStateValidator,
|
|
31
33
|
MemorySessionStore: () => MemorySessionStore,
|
|
32
34
|
NonceManager: () => NonceManager,
|
|
33
35
|
PAFI_ISSUER_SDK_VERSION: () => PAFI_ISSUER_SDK_VERSION,
|
|
@@ -2093,6 +2095,176 @@ function createIssuerService(config) {
|
|
|
2093
2095
|
};
|
|
2094
2096
|
}
|
|
2095
2097
|
|
|
2098
|
+
// src/issuer-state/validator.ts
|
|
2099
|
+
var import_viem11 = require("viem");
|
|
2100
|
+
var import_core9 = require("@pafi-dev/core");
|
|
2101
|
+
|
|
2102
|
+
// src/issuer-state/types.ts
|
|
2103
|
+
var IssuerStateError = class extends Error {
|
|
2104
|
+
constructor(code, message, details) {
|
|
2105
|
+
super(message);
|
|
2106
|
+
this.code = code;
|
|
2107
|
+
this.details = details;
|
|
2108
|
+
this.name = "IssuerStateError";
|
|
2109
|
+
}
|
|
2110
|
+
code;
|
|
2111
|
+
details;
|
|
2112
|
+
};
|
|
2113
|
+
|
|
2114
|
+
// src/issuer-state/validator.ts
|
|
2115
|
+
var ISSUER_RECORD_TTL_MS = 3e4;
|
|
2116
|
+
var IssuerStateValidator = class _IssuerStateValidator {
|
|
2117
|
+
constructor(provider, registryAddress) {
|
|
2118
|
+
this.provider = provider;
|
|
2119
|
+
this.registryAddress = registryAddress;
|
|
2120
|
+
}
|
|
2121
|
+
provider;
|
|
2122
|
+
registryAddress;
|
|
2123
|
+
pointTokenIssuerCache = /* @__PURE__ */ new Map();
|
|
2124
|
+
stateCache = /* @__PURE__ */ new Map();
|
|
2125
|
+
inflight = /* @__PURE__ */ new Map();
|
|
2126
|
+
/**
|
|
2127
|
+
* Convenience factory — reads `registryAddress` from the SDK
|
|
2128
|
+
* `CONTRACT_ADDRESSES` map for the given chain.
|
|
2129
|
+
*/
|
|
2130
|
+
static forChain(provider, chainId) {
|
|
2131
|
+
const { issuerRegistry } = (0, import_core9.getContractAddresses)(chainId);
|
|
2132
|
+
return new _IssuerStateValidator(provider, issuerRegistry);
|
|
2133
|
+
}
|
|
2134
|
+
/**
|
|
2135
|
+
* Invalidate cached state for one PointToken, or everything if omitted.
|
|
2136
|
+
* Call after admin txs that change registry or cap settings.
|
|
2137
|
+
*/
|
|
2138
|
+
invalidate(pointToken) {
|
|
2139
|
+
if (pointToken) {
|
|
2140
|
+
const key = (0, import_viem11.getAddress)(pointToken);
|
|
2141
|
+
this.pointTokenIssuerCache.delete(key);
|
|
2142
|
+
this.stateCache.delete(key);
|
|
2143
|
+
this.inflight.delete(key);
|
|
2144
|
+
} else {
|
|
2145
|
+
this.pointTokenIssuerCache.clear();
|
|
2146
|
+
this.stateCache.clear();
|
|
2147
|
+
this.inflight.clear();
|
|
2148
|
+
}
|
|
2149
|
+
}
|
|
2150
|
+
/**
|
|
2151
|
+
* Resolve `PointToken.issuer()` once per token and memoize.
|
|
2152
|
+
* The issuer field is set at `initialize()` and never changes.
|
|
2153
|
+
*/
|
|
2154
|
+
async getIssuerAddressForPointToken(pointToken) {
|
|
2155
|
+
const key = (0, import_viem11.getAddress)(pointToken);
|
|
2156
|
+
const cached = this.pointTokenIssuerCache.get(key);
|
|
2157
|
+
if (cached) return cached;
|
|
2158
|
+
const issuer = await this.provider.readContract({
|
|
2159
|
+
address: key,
|
|
2160
|
+
abi: import_core9.POINT_TOKEN_V2_ABI,
|
|
2161
|
+
functionName: "issuer"
|
|
2162
|
+
});
|
|
2163
|
+
this.pointTokenIssuerCache.set(key, (0, import_viem11.getAddress)(issuer));
|
|
2164
|
+
return (0, import_viem11.getAddress)(issuer);
|
|
2165
|
+
}
|
|
2166
|
+
/**
|
|
2167
|
+
* Read registry record + totalSupply, with 30s cache and in-flight
|
|
2168
|
+
* deduplication. Does NOT throw on inactive/missing — returns raw state.
|
|
2169
|
+
*/
|
|
2170
|
+
async getIssuerState(pointToken) {
|
|
2171
|
+
const tokenAddr = (0, import_viem11.getAddress)(pointToken);
|
|
2172
|
+
const now = Date.now();
|
|
2173
|
+
const cached = this.stateCache.get(tokenAddr);
|
|
2174
|
+
if (cached && cached.expiresAt > now) return cached.value;
|
|
2175
|
+
const existing = this.inflight.get(tokenAddr);
|
|
2176
|
+
if (existing) return existing;
|
|
2177
|
+
const promise = this.fetchIssuerState(tokenAddr).then((state) => {
|
|
2178
|
+
this.stateCache.set(tokenAddr, {
|
|
2179
|
+
value: state,
|
|
2180
|
+
expiresAt: Date.now() + ISSUER_RECORD_TTL_MS
|
|
2181
|
+
});
|
|
2182
|
+
return state;
|
|
2183
|
+
}).finally(() => {
|
|
2184
|
+
this.inflight.delete(tokenAddr);
|
|
2185
|
+
});
|
|
2186
|
+
this.inflight.set(tokenAddr, promise);
|
|
2187
|
+
return promise;
|
|
2188
|
+
}
|
|
2189
|
+
/**
|
|
2190
|
+
* Validate that `amount` PT can be minted on `pointToken` right now.
|
|
2191
|
+
*
|
|
2192
|
+
* Throws `IssuerStateError` with:
|
|
2193
|
+
* - `ISSUER_NOT_REGISTERED` — registry has no record for this issuer
|
|
2194
|
+
* - `ISSUER_INACTIVE` — issuer.active is false
|
|
2195
|
+
* - `MINT_CAP_EXCEEDED` — totalSupply + amount would exceed hardCap
|
|
2196
|
+
*
|
|
2197
|
+
* Returns the fetched state on success so callers can log without a
|
|
2198
|
+
* second RPC round-trip.
|
|
2199
|
+
*/
|
|
2200
|
+
async preValidateMint(pointToken, amount) {
|
|
2201
|
+
let state;
|
|
2202
|
+
try {
|
|
2203
|
+
state = await this.getIssuerState(pointToken);
|
|
2204
|
+
} catch (err) {
|
|
2205
|
+
if (err.message.includes("IssuerNotFound")) {
|
|
2206
|
+
throw new IssuerStateError(
|
|
2207
|
+
"ISSUER_NOT_REGISTERED",
|
|
2208
|
+
`IssuerRegistry has no record for PointToken ${pointToken}`,
|
|
2209
|
+
{ pointToken }
|
|
2210
|
+
);
|
|
2211
|
+
}
|
|
2212
|
+
throw err;
|
|
2213
|
+
}
|
|
2214
|
+
const { issuer, totalSupply, hardCap, remaining } = state;
|
|
2215
|
+
if (!issuer.active) {
|
|
2216
|
+
throw new IssuerStateError(
|
|
2217
|
+
"ISSUER_INACTIVE",
|
|
2218
|
+
`Issuer ${issuer.issuerAddress} is deactivated on IssuerRegistry`,
|
|
2219
|
+
{ issuer: issuer.issuerAddress, pointToken: issuer.pointToken }
|
|
2220
|
+
);
|
|
2221
|
+
}
|
|
2222
|
+
if (totalSupply + amount > hardCap) {
|
|
2223
|
+
throw new IssuerStateError(
|
|
2224
|
+
"MINT_CAP_EXCEEDED",
|
|
2225
|
+
`Requested ${amount} PT would exceed mint cap. Cap=${hardCap}, minted=${totalSupply}, remaining=${remaining}`,
|
|
2226
|
+
{
|
|
2227
|
+
requested: amount.toString(),
|
|
2228
|
+
cap: hardCap.toString(),
|
|
2229
|
+
minted: totalSupply.toString(),
|
|
2230
|
+
remaining: remaining.toString()
|
|
2231
|
+
}
|
|
2232
|
+
);
|
|
2233
|
+
}
|
|
2234
|
+
return state;
|
|
2235
|
+
}
|
|
2236
|
+
async fetchIssuerState(tokenAddr) {
|
|
2237
|
+
const issuerAddr = await this.getIssuerAddressForPointToken(tokenAddr);
|
|
2238
|
+
const [tuple, totalSupply] = await Promise.all([
|
|
2239
|
+
this.provider.readContract({
|
|
2240
|
+
address: this.registryAddress,
|
|
2241
|
+
abi: import_core9.issuerRegistryAbi,
|
|
2242
|
+
functionName: "getIssuer",
|
|
2243
|
+
args: [issuerAddr]
|
|
2244
|
+
}),
|
|
2245
|
+
this.provider.readContract({
|
|
2246
|
+
address: tokenAddr,
|
|
2247
|
+
abi: import_core9.POINT_TOKEN_V2_ABI,
|
|
2248
|
+
functionName: "totalSupply"
|
|
2249
|
+
})
|
|
2250
|
+
]);
|
|
2251
|
+
const issuer = {
|
|
2252
|
+
issuerAddress: tuple[0],
|
|
2253
|
+
signerAddress: tuple[1],
|
|
2254
|
+
name: tuple[2],
|
|
2255
|
+
symbol: tuple[3],
|
|
2256
|
+
declaredTotalSupply: tuple[4],
|
|
2257
|
+
capBasisPoints: tuple[5],
|
|
2258
|
+
active: tuple[6],
|
|
2259
|
+
pointToken: tuple[7],
|
|
2260
|
+
mintingOracle: tuple[8]
|
|
2261
|
+
};
|
|
2262
|
+
const hardCap = issuer.declaredTotalSupply * BigInt(issuer.capBasisPoints) / 10000n;
|
|
2263
|
+
const remaining = hardCap > totalSupply ? hardCap - totalSupply : 0n;
|
|
2264
|
+
return { issuer, totalSupply, hardCap, remaining };
|
|
2265
|
+
}
|
|
2266
|
+
};
|
|
2267
|
+
|
|
2096
2268
|
// src/index.ts
|
|
2097
2269
|
var PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
2098
2270
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -2105,6 +2277,8 @@ var PAFI_ISSUER_SDK_VERSION = "0.4.0";
|
|
|
2105
2277
|
FeeManager,
|
|
2106
2278
|
InMemoryCursorStore,
|
|
2107
2279
|
IssuerApiHandlers,
|
|
2280
|
+
IssuerStateError,
|
|
2281
|
+
IssuerStateValidator,
|
|
2108
2282
|
MemorySessionStore,
|
|
2109
2283
|
NonceManager,
|
|
2110
2284
|
PAFI_ISSUER_SDK_VERSION,
|