@flapsdk/vault-runtime 0.1.0 → 0.1.2
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/README.md +2 -2
- package/host.d.mts +4 -4
- package/host.js +123 -25
- package/host.js.map +1 -1
- package/{hostRuntimeConfig-BOEJo2nq.d.mts → hostRuntimeConfig-8d2c6qsO.d.mts} +1 -1
- package/package.json +1 -1
- package/runtime-contract.json +1 -1
- package/sdk.d.mts +6 -5
- package/sdk.js +120 -24
- package/sdk.js.map +1 -1
- package/server.d.mts +15 -4
- package/server.js +136 -9
- package/server.js.map +1 -1
- package/{txError-1lPZHdqI.d.mts → txError-BmDt5Z4B.d.mts} +25 -3
- package/{types-CX7pLmiT.d.mts → types-DzTX2u7q.d.mts} +20 -2
- package/ui.js.map +1 -1
package/server.js
CHANGED
|
@@ -49,20 +49,24 @@ function resolveIpfsGateway(chainId) {
|
|
|
49
49
|
return getTaxVaultHostChainConfig(chainId)?.ipfsGateway ?? DEFAULT_IPFS_GATEWAY;
|
|
50
50
|
}
|
|
51
51
|
function rewriteToPublicIpfsGateway(rawUrl, chainId) {
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
52
|
+
try {
|
|
53
|
+
const gateway = resolveIpfsGateway(chainId);
|
|
54
|
+
const parsed = new URL(rawUrl);
|
|
55
|
+
if (!LEGACY_IPFS_GATEWAY_HOSTS.has(parsed.hostname)) return rawUrl;
|
|
56
|
+
const publicGateway = new URL(gateway);
|
|
57
|
+
parsed.protocol = publicGateway.protocol;
|
|
58
|
+
parsed.host = publicGateway.host;
|
|
59
|
+
return parsed.toString();
|
|
60
|
+
} catch {
|
|
61
|
+
return void 0;
|
|
62
|
+
}
|
|
59
63
|
}
|
|
60
64
|
function wrapHostImageUrl(image, chainId) {
|
|
61
65
|
const raw = normalizeString(image);
|
|
62
66
|
if (!raw) return void 0;
|
|
63
67
|
if (raw.startsWith("/")) return raw;
|
|
64
68
|
if (raw.startsWith("https://")) return rewriteToPublicIpfsGateway(raw, chainId);
|
|
65
|
-
if (raw.startsWith("http://")) return
|
|
69
|
+
if (raw.startsWith("http://")) return void 0;
|
|
66
70
|
const gateway = resolveIpfsGateway(chainId).replace(/\/+$/, "");
|
|
67
71
|
if (raw.startsWith("ipfs://")) return `${gateway}/ipfs/${raw.slice("ipfs://".length)}`;
|
|
68
72
|
return `${gateway}/ipfs/${raw}`;
|
|
@@ -195,6 +199,129 @@ function createLocalHostPresentationFetcher(options = {}) {
|
|
|
195
199
|
};
|
|
196
200
|
}
|
|
197
201
|
|
|
198
|
-
|
|
202
|
+
// src/sdk/oracle.ts
|
|
203
|
+
var OracleReadError = class extends Error {
|
|
204
|
+
constructor(message, status) {
|
|
205
|
+
super(message);
|
|
206
|
+
this.name = "OracleReadError";
|
|
207
|
+
this.status = status;
|
|
208
|
+
}
|
|
209
|
+
};
|
|
210
|
+
function appendSearchParams(url, params) {
|
|
211
|
+
for (const [key, value] of Object.entries(params ?? {})) {
|
|
212
|
+
url.searchParams.set(key, value);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
function toOracleProvision(provision) {
|
|
216
|
+
return typeof provision === "string" ? { endpoint: provision } : provision;
|
|
217
|
+
}
|
|
218
|
+
async function fetchOracleJson({
|
|
219
|
+
endpoint,
|
|
220
|
+
params,
|
|
221
|
+
fetchImpl,
|
|
222
|
+
headers
|
|
223
|
+
}) {
|
|
224
|
+
const fallbackOrigin = typeof window !== "undefined" ? window.location.origin : "http://localhost";
|
|
225
|
+
const url = new URL(endpoint, fallbackOrigin);
|
|
226
|
+
appendSearchParams(url, params);
|
|
227
|
+
const response = await (fetchImpl ?? fetch)(url.toString(), {
|
|
228
|
+
cache: "no-store",
|
|
229
|
+
headers,
|
|
230
|
+
method: "GET"
|
|
231
|
+
});
|
|
232
|
+
if (!response.ok) {
|
|
233
|
+
throw new OracleReadError(`Oracle request returned ${response.status}.`, response.status);
|
|
234
|
+
}
|
|
235
|
+
return await response.json();
|
|
236
|
+
}
|
|
237
|
+
async function fetchProvisionedOracle({
|
|
238
|
+
provision,
|
|
239
|
+
params,
|
|
240
|
+
fetchImpl
|
|
241
|
+
}) {
|
|
242
|
+
const normalizedProvision = toOracleProvision(provision);
|
|
243
|
+
const filteredParams = normalizedProvision.allowedParams && normalizedProvision.allowedParams.length ? Object.fromEntries(Object.entries(params ?? {}).filter(([key]) => normalizedProvision.allowedParams?.includes(key))) : params;
|
|
244
|
+
return fetchOracleJson({
|
|
245
|
+
endpoint: normalizedProvision.endpoint,
|
|
246
|
+
params: filteredParams,
|
|
247
|
+
fetchImpl,
|
|
248
|
+
headers: normalizedProvision.headers
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// src/sdk/oracleServer.ts
|
|
253
|
+
var FLAP_RUNTIME_ORACLE_REGISTRY_ENV = "FLAP_RUNTIME_ORACLE_REGISTRY";
|
|
254
|
+
var DEFAULT_EXAMPLE_ORACLE_SIGNATURE = "0x000000000000000000000000000000000000dEaD";
|
|
255
|
+
function normalizeHeaders(headers) {
|
|
256
|
+
if (!headers || typeof headers !== "object" || Array.isArray(headers)) return void 0;
|
|
257
|
+
const entries = Object.entries(headers).filter(([, value]) => typeof value === "string").map(([key, value]) => [key, value.trim()]).filter(([, value]) => value);
|
|
258
|
+
return entries.length ? Object.fromEntries(entries) : void 0;
|
|
259
|
+
}
|
|
260
|
+
function normalizeAllowedParams(value) {
|
|
261
|
+
if (!Array.isArray(value)) return void 0;
|
|
262
|
+
const params = value.filter((item) => typeof item === "string" && item.trim().length > 0);
|
|
263
|
+
return params.length ? params : void 0;
|
|
264
|
+
}
|
|
265
|
+
function normalizeProvision(value) {
|
|
266
|
+
if (typeof value === "string") {
|
|
267
|
+
return value.trim() ? { endpoint: value.trim() } : null;
|
|
268
|
+
}
|
|
269
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
270
|
+
const record = value;
|
|
271
|
+
if (typeof record.endpoint !== "string" || !record.endpoint.trim()) return null;
|
|
272
|
+
return {
|
|
273
|
+
endpoint: record.endpoint.trim(),
|
|
274
|
+
headers: normalizeHeaders(record.headers),
|
|
275
|
+
allowedParams: normalizeAllowedParams(record.allowedParams)
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
function parseRuntimeOracleRegistry(raw) {
|
|
279
|
+
if (!raw?.trim()) return {};
|
|
280
|
+
let parsed;
|
|
281
|
+
try {
|
|
282
|
+
parsed = JSON.parse(raw);
|
|
283
|
+
} catch (error) {
|
|
284
|
+
throw new Error(
|
|
285
|
+
`${FLAP_RUNTIME_ORACLE_REGISTRY_ENV} must be valid JSON: ${error instanceof Error ? error.message : String(error)}`
|
|
286
|
+
);
|
|
287
|
+
}
|
|
288
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
289
|
+
throw new Error(`${FLAP_RUNTIME_ORACLE_REGISTRY_ENV} must be a JSON object keyed by oracle id.`);
|
|
290
|
+
}
|
|
291
|
+
return Object.fromEntries(
|
|
292
|
+
Object.entries(parsed).map(([oracleId, provision]) => [oracleId, normalizeProvision(provision)]).filter((entry) => Boolean(entry[1]))
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
function resolveRuntimeOracleProvision(oracleId, registry) {
|
|
296
|
+
const provision = registry[oracleId];
|
|
297
|
+
if (!provision) return null;
|
|
298
|
+
return typeof provision === "string" ? { endpoint: provision } : provision;
|
|
299
|
+
}
|
|
300
|
+
function loadDefaultRuntimeOracle(oracleId) {
|
|
301
|
+
if (oracleId === "example-reward-oracle") {
|
|
302
|
+
return {
|
|
303
|
+
rewardMultiplierBps: 175,
|
|
304
|
+
timestamp: Math.floor(Date.now() / 1e3),
|
|
305
|
+
signature: DEFAULT_EXAMPLE_ORACLE_SIGNATURE
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
async function loadRuntimeOracle({
|
|
311
|
+
oracleId,
|
|
312
|
+
params,
|
|
313
|
+
registry,
|
|
314
|
+
fetchImpl
|
|
315
|
+
}) {
|
|
316
|
+
const provision = resolveRuntimeOracleProvision(oracleId, registry);
|
|
317
|
+
if (!provision) return null;
|
|
318
|
+
return fetchProvisionedOracle({
|
|
319
|
+
provision,
|
|
320
|
+
params,
|
|
321
|
+
fetchImpl
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export { FLAP_RUNTIME_ORACLE_REGISTRY_ENV, createLocalHostPresentationFetcher, getTaxVaultHostChainConfig, loadDefaultRuntimeOracle, loadFlapHostTokenPresentation, loadFlapHostTokenPresentationBatch, loadRuntimeOracle, parseRuntimeOracleRegistry, resolveRuntimeOracleProvision };
|
|
199
326
|
//# sourceMappingURL=server.js.map
|
|
200
327
|
//# sourceMappingURL=server.js.map
|
package/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/sdk/hostRuntimeConfig.ts","../../src/sdk/hostPresentation.ts"],"names":[],"mappings":"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","file":"server.js","sourcesContent":["import type { Address } from \"./types\";\n\nexport interface TaxVaultHostChainConfig {\n portal: Address;\n taxTokenHelperAddress?: Address;\n vaultPortal?: Address;\n wrappedNativeTokenAddress?: Address;\n giftVaultFactory?: Address;\n hostChainSlug?: string;\n ipfsGateway?: string;\n}\n\nconst taxVaultHostChains: Record<number, TaxVaultHostChainConfig> = {\n 56: {\n portal: \"0xe2ce6ab80874fa9fa2aae65d277dd6b8e65c9de0\",\n taxTokenHelperAddress: \"0x53841c73217735F37BC1775538b03b23feFD8346\",\n vaultPortal: \"0x90497450f2a706f1951b5bdda52B4E5d16f34C06\",\n wrappedNativeTokenAddress: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\",\n giftVaultFactory: \"0x025549F52B03cF36f9e1a337c02d3AA7Af66ab32\",\n hostChainSlug: \"bnb\",\n ipfsGateway: \"https://gateway.pinata.cloud\",\n },\n 97: {\n portal: \"0x5bEacaF7ABCbB3aB280e80D007FD31fcE26510e9\",\n taxTokenHelperAddress: \"0xD64441e5FcD02D342B8cf6eBA10Ef6E40d0dA90f\",\n vaultPortal: \"0x027e3704fC5C16522e9393d04C60A3ac5c0d775f\",\n wrappedNativeTokenAddress: \"0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd\",\n giftVaultFactory: \"0xa02DA44D67DB6D692efa7f751b5952bd670d5326\",\n hostChainSlug: \"bnb-testnet\",\n ipfsGateway: \"https://gateway.pinata.cloud\",\n },\n};\n\nexport function getTaxVaultHostChainConfig(chainId: number) {\n return taxVaultHostChains[chainId];\n}\n","import { getAddress, isAddress } from \"viem\";\nimport { getTaxVaultHostChainConfig } from \"./hostRuntimeConfig\";\nimport type { Address, HostRuntimePresentationFetcher, HostTokenPresentation } from \"./types\";\n\nconst DEFAULT_FLAP_HOST_ORIGIN = \"https://flap.sh\";\nconst DEFAULT_RUNTIME_PRESENTATION_ENDPOINT = \"/api/runtime/token-presentation\";\nconst DEFAULT_IPFS_GATEWAY = \"https://gateway.pinata.cloud\";\nconst LEGACY_IPFS_GATEWAY_HOSTS = new Set([\"cf-ipfs.com\", \"pump.mypinata.cloud\", \"gateway.pinata.cloud\"]);\n\ninterface HostMetadataResponseItem {\n address?: string;\n name?: string;\n symbol?: string;\n metadata?: {\n image?: string;\n description?: string;\n };\n}\n\ninterface HostMetadataResponseBody {\n data?: Record<string, HostMetadataResponseItem> | null;\n}\n\nexport interface ResolveHostPresentationInput {\n chainId: number;\n tokenAddress: Address;\n flapHostOrigin?: string;\n fetchImpl?: typeof fetch;\n}\n\nexport interface ResolveHostPresentationBatchInput {\n chainId: number;\n tokenAddresses: Address[];\n flapHostOrigin?: string;\n fetchImpl?: typeof fetch;\n}\n\nexport interface LocalHostPresentationFetcherOptions {\n endpoint?: string;\n fetchImpl?: typeof fetch;\n}\n\nfunction normalizeOrigin(origin?: string) {\n if (!origin) return DEFAULT_FLAP_HOST_ORIGIN;\n return origin.replace(/\\/+$/, \"\");\n}\n\nfunction normalizeAddress(address: string): Address | null {\n return isAddress(address) ? (getAddress(address) as Address) : null;\n}\n\nfunction normalizeString(value: unknown) {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction resolveHostChainSlug(chainId: number) {\n return getTaxVaultHostChainConfig(chainId)?.hostChainSlug;\n}\n\nfunction resolveIpfsGateway(chainId: number) {\n return getTaxVaultHostChainConfig(chainId)?.ipfsGateway ?? DEFAULT_IPFS_GATEWAY;\n}\n\nfunction rewriteToPublicIpfsGateway(rawUrl: string, chainId: number) {\n const gateway = resolveIpfsGateway(chainId);\n const parsed = new URL(rawUrl);\n if (!LEGACY_IPFS_GATEWAY_HOSTS.has(parsed.hostname)) return rawUrl;\n\n const publicGateway = new URL(gateway);\n parsed.protocol = publicGateway.protocol;\n parsed.host = publicGateway.host;\n return parsed.toString();\n}\n\nfunction wrapHostImageUrl(image: string | undefined, chainId: number) {\n const raw = normalizeString(image);\n if (!raw) return undefined;\n if (raw.startsWith(\"/\")) return raw;\n if (raw.startsWith(\"https://\")) return rewriteToPublicIpfsGateway(raw, chainId);\n if (raw.startsWith(\"http://\")) return raw;\n\n const gateway = resolveIpfsGateway(chainId).replace(/\\/+$/, \"\");\n if (raw.startsWith(\"ipfs://\")) return `${gateway}/ipfs/${raw.slice(\"ipfs://\".length)}`;\n return `${gateway}/ipfs/${raw}`;\n}\n\nfunction buildTokenDetailHref(origin: string, chainSlug: string, tokenAddress: Address) {\n return `${origin}/${chainSlug}/${tokenAddress.toLowerCase()}/taxinfo`;\n}\n\nfunction buildChainHref(origin: string, chainSlug: string) {\n return `${origin}/${chainSlug}`;\n}\n\nfunction resolveMetadataItem(payload: HostMetadataResponseBody | null | undefined, tokenAddress: Address) {\n const data = payload?.data;\n if (!data || typeof data !== \"object\") return null;\n\n const checksum = getAddress(tokenAddress);\n const lower = tokenAddress.toLowerCase();\n const direct = data[checksum] ?? data[lower];\n if (direct && typeof direct === \"object\") return direct;\n\n for (const value of Object.values(data)) {\n if (!value || typeof value !== \"object\") continue;\n const itemAddress = normalizeString((value as HostMetadataResponseItem).address);\n if (itemAddress && normalizeAddress(itemAddress)?.toLowerCase() === lower) {\n return value;\n }\n }\n\n return null;\n}\n\nfunction toHostPresentation(chainId: number, tokenAddress: Address, flapHostOrigin: string, item: HostMetadataResponseItem | null): HostTokenPresentation | null {\n if (!item) return null;\n\n const chainSlug = resolveHostChainSlug(chainId);\n if (!chainSlug) return null;\n\n const tokenSymbol = normalizeString(item.symbol);\n const tokenName = normalizeString(item.name);\n const tokenImageUrl = wrapHostImageUrl(item.metadata?.image, chainId);\n\n if (!tokenSymbol && !tokenName && !tokenImageUrl) return null;\n\n return {\n tokenSymbol,\n tokenName,\n tokenImageUrl,\n tokenDetailHref: buildTokenDetailHref(flapHostOrigin, chainSlug, tokenAddress),\n chainHref: buildChainHref(flapHostOrigin, chainSlug),\n extraConfig: {\n hostPresentationOrigin: flapHostOrigin,\n hostPresentationChain: chainSlug,\n ...(normalizeString(item.metadata?.description) ? { tokenDescription: normalizeString(item.metadata?.description) } : {}),\n },\n };\n}\n\nexport async function loadFlapHostTokenPresentation(input: ResolveHostPresentationInput): Promise<HostTokenPresentation | null> {\n const chainSlug = resolveHostChainSlug(input.chainId);\n if (!chainSlug) return null;\n\n const tokenAddress = normalizeAddress(input.tokenAddress);\n if (!tokenAddress) return null;\n\n const flapHostOrigin = normalizeOrigin(input.flapHostOrigin);\n const fetchImpl = input.fetchImpl ?? fetch;\n const response = await fetchImpl(`${flapHostOrigin}/api/tax-dashboard/metadata`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n chain: chainSlug,\n addresses: [tokenAddress.toLowerCase()],\n }),\n cache: \"no-store\",\n });\n\n if (!response.ok) return null;\n\n const payload = (await response.json()) as HostMetadataResponseBody;\n return toHostPresentation(input.chainId, tokenAddress, flapHostOrigin, resolveMetadataItem(payload, tokenAddress));\n}\n\nexport async function loadFlapHostTokenPresentationBatch(input: ResolveHostPresentationBatchInput): Promise<Record<string, HostTokenPresentation | null>> {\n const chainSlug = resolveHostChainSlug(input.chainId);\n if (!chainSlug) return {};\n\n const normalizedAddresses = input.tokenAddresses\n .map((tokenAddress) => normalizeAddress(tokenAddress))\n .filter((tokenAddress): tokenAddress is Address => Boolean(tokenAddress));\n if (!normalizedAddresses.length) return {};\n\n const flapHostOrigin = normalizeOrigin(input.flapHostOrigin);\n const fetchImpl = input.fetchImpl ?? fetch;\n const response = await fetchImpl(`${flapHostOrigin}/api/tax-dashboard/metadata`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n chain: chainSlug,\n addresses: normalizedAddresses.map((tokenAddress) => tokenAddress.toLowerCase()),\n }),\n cache: \"no-store\",\n });\n\n if (!response.ok) return {};\n\n const payload = (await response.json()) as HostMetadataResponseBody;\n return Object.fromEntries(\n normalizedAddresses.map((tokenAddress) => [\n tokenAddress,\n toHostPresentation(input.chainId, tokenAddress, flapHostOrigin, resolveMetadataItem(payload, tokenAddress)),\n ]),\n );\n}\n\nfunction parsePresentationPayload(payload: unknown): HostTokenPresentation | null {\n if (!payload || typeof payload !== \"object\") return null;\n const record = payload as Record<string, unknown>;\n const tokenSymbol = normalizeString(record.tokenSymbol);\n const tokenName = normalizeString(record.tokenName);\n const tokenImageUrl = normalizeString(record.tokenImageUrl);\n\n if (!tokenSymbol && !tokenName && !tokenImageUrl) return null;\n\n return {\n tokenSymbol,\n tokenName,\n tokenImageUrl,\n tokenDetailHref: normalizeString(record.tokenDetailHref),\n chainHref: normalizeString(record.chainHref),\n extraConfig: record.extraConfig && typeof record.extraConfig === \"object\" && !Array.isArray(record.extraConfig) ? (record.extraConfig as Record<string, unknown>) : undefined,\n };\n}\n\nexport function createLocalHostPresentationFetcher(options: LocalHostPresentationFetcherOptions = {}): HostRuntimePresentationFetcher {\n const endpoint = options.endpoint ?? DEFAULT_RUNTIME_PRESENTATION_ENDPOINT;\n const fetchImpl = options.fetchImpl ?? fetch;\n\n return async ({ chainId, tokenAddress, factoryAddress, vaultAddress }) => {\n const query = new URLSearchParams({\n chainId: String(chainId),\n tokenAddress,\n });\n if (factoryAddress) query.set(\"factoryAddress\", factoryAddress);\n if (vaultAddress) query.set(\"vaultAddress\", vaultAddress);\n\n const response = await fetchImpl(`${endpoint}?${query.toString()}`, {\n method: \"GET\",\n cache: \"no-store\",\n });\n if (!response.ok) return null;\n\n const payload = (await response.json()) as { data?: unknown } | null;\n return parsePresentationPayload(payload?.data);\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/sdk/hostRuntimeConfig.ts","../../src/sdk/hostPresentation.ts","../../src/sdk/oracle.ts","../../src/sdk/oracleServer.ts"],"names":[],"mappings":"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","file":"server.js","sourcesContent":["import type { Address } from \"./types\";\n\nexport interface TaxVaultHostChainConfig {\n portal: Address;\n taxTokenHelperAddress?: Address;\n vaultPortal?: Address;\n wrappedNativeTokenAddress?: Address;\n giftVaultFactory?: Address;\n hostChainSlug?: string;\n ipfsGateway?: string;\n}\n\nconst taxVaultHostChains: Record<number, TaxVaultHostChainConfig> = {\n 56: {\n portal: \"0xe2ce6ab80874fa9fa2aae65d277dd6b8e65c9de0\",\n taxTokenHelperAddress: \"0x53841c73217735F37BC1775538b03b23feFD8346\",\n vaultPortal: \"0x90497450f2a706f1951b5bdda52B4E5d16f34C06\",\n wrappedNativeTokenAddress: \"0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c\",\n giftVaultFactory: \"0x025549F52B03cF36f9e1a337c02d3AA7Af66ab32\",\n hostChainSlug: \"bnb\",\n ipfsGateway: \"https://gateway.pinata.cloud\",\n },\n 97: {\n portal: \"0x5bEacaF7ABCbB3aB280e80D007FD31fcE26510e9\",\n taxTokenHelperAddress: \"0xD64441e5FcD02D342B8cf6eBA10Ef6E40d0dA90f\",\n vaultPortal: \"0x027e3704fC5C16522e9393d04C60A3ac5c0d775f\",\n wrappedNativeTokenAddress: \"0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd\",\n giftVaultFactory: \"0xa02DA44D67DB6D692efa7f751b5952bd670d5326\",\n hostChainSlug: \"bnb-testnet\",\n ipfsGateway: \"https://gateway.pinata.cloud\",\n },\n};\n\nexport function getTaxVaultHostChainConfig(chainId: number) {\n return taxVaultHostChains[chainId];\n}\n","import { getAddress, isAddress } from \"viem\";\nimport { getTaxVaultHostChainConfig } from \"./hostRuntimeConfig\";\nimport type { Address, HostRuntimePresentationFetcher, HostTokenPresentation } from \"./types\";\n\nconst DEFAULT_FLAP_HOST_ORIGIN = \"https://flap.sh\";\nconst DEFAULT_RUNTIME_PRESENTATION_ENDPOINT = \"/api/runtime/token-presentation\";\nconst DEFAULT_IPFS_GATEWAY = \"https://gateway.pinata.cloud\";\nconst LEGACY_IPFS_GATEWAY_HOSTS = new Set([\"cf-ipfs.com\", \"pump.mypinata.cloud\", \"gateway.pinata.cloud\"]);\n\ninterface HostMetadataResponseItem {\n address?: string;\n name?: string;\n symbol?: string;\n metadata?: {\n image?: string;\n description?: string;\n };\n}\n\ninterface HostMetadataResponseBody {\n data?: Record<string, HostMetadataResponseItem> | null;\n}\n\nexport interface ResolveHostPresentationInput {\n chainId: number;\n tokenAddress: Address;\n flapHostOrigin?: string;\n fetchImpl?: typeof fetch;\n}\n\nexport interface ResolveHostPresentationBatchInput {\n chainId: number;\n tokenAddresses: Address[];\n flapHostOrigin?: string;\n fetchImpl?: typeof fetch;\n}\n\nexport interface LocalHostPresentationFetcherOptions {\n endpoint?: string;\n fetchImpl?: typeof fetch;\n}\n\nfunction normalizeOrigin(origin?: string) {\n if (!origin) return DEFAULT_FLAP_HOST_ORIGIN;\n return origin.replace(/\\/+$/, \"\");\n}\n\nfunction normalizeAddress(address: string): Address | null {\n return isAddress(address) ? (getAddress(address) as Address) : null;\n}\n\nfunction normalizeString(value: unknown) {\n return typeof value === \"string\" && value.trim() ? value.trim() : undefined;\n}\n\nfunction resolveHostChainSlug(chainId: number) {\n return getTaxVaultHostChainConfig(chainId)?.hostChainSlug;\n}\n\nfunction resolveIpfsGateway(chainId: number) {\n return getTaxVaultHostChainConfig(chainId)?.ipfsGateway ?? DEFAULT_IPFS_GATEWAY;\n}\n\nfunction rewriteToPublicIpfsGateway(rawUrl: string, chainId: number) {\n try {\n const gateway = resolveIpfsGateway(chainId);\n const parsed = new URL(rawUrl);\n if (!LEGACY_IPFS_GATEWAY_HOSTS.has(parsed.hostname)) return rawUrl;\n\n const publicGateway = new URL(gateway);\n parsed.protocol = publicGateway.protocol;\n parsed.host = publicGateway.host;\n return parsed.toString();\n } catch {\n return undefined;\n }\n}\n\nfunction wrapHostImageUrl(image: string | undefined, chainId: number) {\n const raw = normalizeString(image);\n if (!raw) return undefined;\n if (raw.startsWith(\"/\")) return raw;\n if (raw.startsWith(\"https://\")) return rewriteToPublicIpfsGateway(raw, chainId);\n if (raw.startsWith(\"http://\")) return undefined;\n\n const gateway = resolveIpfsGateway(chainId).replace(/\\/+$/, \"\");\n if (raw.startsWith(\"ipfs://\")) return `${gateway}/ipfs/${raw.slice(\"ipfs://\".length)}`;\n return `${gateway}/ipfs/${raw}`;\n}\n\nfunction buildTokenDetailHref(origin: string, chainSlug: string, tokenAddress: Address) {\n return `${origin}/${chainSlug}/${tokenAddress.toLowerCase()}/taxinfo`;\n}\n\nfunction buildChainHref(origin: string, chainSlug: string) {\n return `${origin}/${chainSlug}`;\n}\n\nfunction resolveMetadataItem(payload: HostMetadataResponseBody | null | undefined, tokenAddress: Address) {\n const data = payload?.data;\n if (!data || typeof data !== \"object\") return null;\n\n const checksum = getAddress(tokenAddress);\n const lower = tokenAddress.toLowerCase();\n const direct = data[checksum] ?? data[lower];\n if (direct && typeof direct === \"object\") return direct;\n\n for (const value of Object.values(data)) {\n if (!value || typeof value !== \"object\") continue;\n const itemAddress = normalizeString((value as HostMetadataResponseItem).address);\n if (itemAddress && normalizeAddress(itemAddress)?.toLowerCase() === lower) {\n return value;\n }\n }\n\n return null;\n}\n\nfunction toHostPresentation(chainId: number, tokenAddress: Address, flapHostOrigin: string, item: HostMetadataResponseItem | null): HostTokenPresentation | null {\n if (!item) return null;\n\n const chainSlug = resolveHostChainSlug(chainId);\n if (!chainSlug) return null;\n\n const tokenSymbol = normalizeString(item.symbol);\n const tokenName = normalizeString(item.name);\n const tokenImageUrl = wrapHostImageUrl(item.metadata?.image, chainId);\n\n if (!tokenSymbol && !tokenName && !tokenImageUrl) return null;\n\n return {\n tokenSymbol,\n tokenName,\n tokenImageUrl,\n tokenDetailHref: buildTokenDetailHref(flapHostOrigin, chainSlug, tokenAddress),\n chainHref: buildChainHref(flapHostOrigin, chainSlug),\n extraConfig: {\n hostPresentationOrigin: flapHostOrigin,\n hostPresentationChain: chainSlug,\n ...(normalizeString(item.metadata?.description) ? { tokenDescription: normalizeString(item.metadata?.description) } : {}),\n },\n };\n}\n\nexport async function loadFlapHostTokenPresentation(input: ResolveHostPresentationInput): Promise<HostTokenPresentation | null> {\n const chainSlug = resolveHostChainSlug(input.chainId);\n if (!chainSlug) return null;\n\n const tokenAddress = normalizeAddress(input.tokenAddress);\n if (!tokenAddress) return null;\n\n const flapHostOrigin = normalizeOrigin(input.flapHostOrigin);\n const fetchImpl = input.fetchImpl ?? fetch;\n const response = await fetchImpl(`${flapHostOrigin}/api/tax-dashboard/metadata`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n chain: chainSlug,\n addresses: [tokenAddress.toLowerCase()],\n }),\n cache: \"no-store\",\n });\n\n if (!response.ok) return null;\n\n const payload = (await response.json()) as HostMetadataResponseBody;\n return toHostPresentation(input.chainId, tokenAddress, flapHostOrigin, resolveMetadataItem(payload, tokenAddress));\n}\n\nexport async function loadFlapHostTokenPresentationBatch(input: ResolveHostPresentationBatchInput): Promise<Record<string, HostTokenPresentation | null>> {\n const chainSlug = resolveHostChainSlug(input.chainId);\n if (!chainSlug) return {};\n\n const normalizedAddresses = input.tokenAddresses\n .map((tokenAddress) => normalizeAddress(tokenAddress))\n .filter((tokenAddress): tokenAddress is Address => Boolean(tokenAddress));\n if (!normalizedAddresses.length) return {};\n\n const flapHostOrigin = normalizeOrigin(input.flapHostOrigin);\n const fetchImpl = input.fetchImpl ?? fetch;\n const response = await fetchImpl(`${flapHostOrigin}/api/tax-dashboard/metadata`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n chain: chainSlug,\n addresses: normalizedAddresses.map((tokenAddress) => tokenAddress.toLowerCase()),\n }),\n cache: \"no-store\",\n });\n\n if (!response.ok) return {};\n\n const payload = (await response.json()) as HostMetadataResponseBody;\n return Object.fromEntries(\n normalizedAddresses.map((tokenAddress) => [\n tokenAddress,\n toHostPresentation(input.chainId, tokenAddress, flapHostOrigin, resolveMetadataItem(payload, tokenAddress)),\n ]),\n );\n}\n\nfunction parsePresentationPayload(payload: unknown): HostTokenPresentation | null {\n if (!payload || typeof payload !== \"object\") return null;\n const record = payload as Record<string, unknown>;\n const tokenSymbol = normalizeString(record.tokenSymbol);\n const tokenName = normalizeString(record.tokenName);\n const tokenImageUrl = normalizeString(record.tokenImageUrl);\n\n if (!tokenSymbol && !tokenName && !tokenImageUrl) return null;\n\n return {\n tokenSymbol,\n tokenName,\n tokenImageUrl,\n tokenDetailHref: normalizeString(record.tokenDetailHref),\n chainHref: normalizeString(record.chainHref),\n extraConfig: record.extraConfig && typeof record.extraConfig === \"object\" && !Array.isArray(record.extraConfig) ? (record.extraConfig as Record<string, unknown>) : undefined,\n };\n}\n\nexport function createLocalHostPresentationFetcher(options: LocalHostPresentationFetcherOptions = {}): HostRuntimePresentationFetcher {\n const endpoint = options.endpoint ?? DEFAULT_RUNTIME_PRESENTATION_ENDPOINT;\n const fetchImpl = options.fetchImpl ?? fetch;\n\n return async ({ chainId, tokenAddress, factoryAddress, vaultAddress }) => {\n const query = new URLSearchParams({\n chainId: String(chainId),\n tokenAddress,\n });\n if (factoryAddress) query.set(\"factoryAddress\", factoryAddress);\n if (vaultAddress) query.set(\"vaultAddress\", vaultAddress);\n\n const response = await fetchImpl(`${endpoint}?${query.toString()}`, {\n method: \"GET\",\n cache: \"no-store\",\n });\n if (!response.ok) return null;\n\n const payload = (await response.json()) as { data?: unknown } | null;\n return parsePresentationPayload(payload?.data);\n };\n}\n","import type { OracleProvision, OracleReadRequest, OracleReader } from \"./types\";\n\nconst DEFAULT_LOCAL_ORACLE_ENDPOINT_BASE = \"/api/runtime/oracle\";\n\nexport class OracleReadError extends Error {\n status?: number;\n\n constructor(message: string, status?: number) {\n super(message);\n this.name = \"OracleReadError\";\n this.status = status;\n }\n}\n\nfunction appendSearchParams(url: URL, params?: Record<string, string>) {\n for (const [key, value] of Object.entries(params ?? {})) {\n url.searchParams.set(key, value);\n }\n}\n\nfunction toOracleProvision(provision: string | OracleProvision): OracleProvision {\n return typeof provision === \"string\" ? { endpoint: provision } : provision;\n}\n\nexport function buildLocalOracleUrl(oracleId: string, params?: Record<string, string>, endpointBase = DEFAULT_LOCAL_ORACLE_ENDPOINT_BASE) {\n const normalizedBase = endpointBase.replace(/\\/+$/, \"\");\n const url = new URL(`${normalizedBase}/${encodeURIComponent(oracleId)}`, \"http://localhost\");\n appendSearchParams(url, params);\n return `${url.pathname}${url.search}`;\n}\n\nexport async function fetchOracleJson<T>({\n endpoint,\n params,\n fetchImpl,\n headers,\n}: {\n endpoint: string;\n params?: Record<string, string>;\n fetchImpl?: typeof fetch;\n headers?: HeadersInit;\n}): Promise<T> {\n const fallbackOrigin = typeof window !== \"undefined\" ? window.location.origin : \"http://localhost\";\n const url = new URL(endpoint, fallbackOrigin);\n appendSearchParams(url, params);\n\n const response = await (fetchImpl ?? fetch)(url.toString(), {\n cache: \"no-store\",\n headers,\n method: \"GET\",\n });\n\n if (!response.ok) {\n throw new OracleReadError(`Oracle request returned ${response.status}.`, response.status);\n }\n\n return (await response.json()) as T;\n}\n\nexport async function fetchProvisionedOracle<T>({\n provision,\n params,\n fetchImpl,\n}: {\n provision: string | OracleProvision;\n params?: Record<string, string>;\n fetchImpl?: typeof fetch;\n}): Promise<T> {\n const normalizedProvision = toOracleProvision(provision);\n const filteredParams =\n normalizedProvision.allowedParams && normalizedProvision.allowedParams.length\n ? Object.fromEntries(Object.entries(params ?? {}).filter(([key]) => normalizedProvision.allowedParams?.includes(key)))\n : params;\n\n return fetchOracleJson<T>({\n endpoint: normalizedProvision.endpoint,\n params: filteredParams,\n fetchImpl,\n headers: normalizedProvision.headers,\n });\n}\n\nexport function createLocalOracleReader(options: { endpointBase?: string; fetchImpl?: typeof fetch } = {}): OracleReader {\n const endpointBase = options.endpointBase ?? DEFAULT_LOCAL_ORACLE_ENDPOINT_BASE;\n const fetchImpl = options.fetchImpl;\n\n return async function readLocalOracle<T>({ oracleId, params }: OracleReadRequest): Promise<T> {\n return fetchOracleJson<T>({\n endpoint: buildLocalOracleUrl(oracleId, params, endpointBase),\n fetchImpl,\n });\n };\n}\n","import { fetchProvisionedOracle } from \"./oracle\";\nimport type { Address, OracleProvision, RuntimeOracleRegistry } from \"./types\";\n\nexport const FLAP_RUNTIME_ORACLE_REGISTRY_ENV = \"FLAP_RUNTIME_ORACLE_REGISTRY\";\nconst DEFAULT_EXAMPLE_ORACLE_SIGNATURE = \"0x000000000000000000000000000000000000dEaD\" as Address;\n\nfunction normalizeHeaders(headers: unknown) {\n if (!headers || typeof headers !== \"object\" || Array.isArray(headers)) return undefined;\n const entries = Object.entries(headers)\n .filter(([, value]) => typeof value === \"string\")\n .map(([key, value]) => [key, value.trim()] as const)\n .filter(([, value]) => value);\n return entries.length ? Object.fromEntries(entries) : undefined;\n}\n\nfunction normalizeAllowedParams(value: unknown) {\n if (!Array.isArray(value)) return undefined;\n const params = value.filter((item): item is string => typeof item === \"string\" && item.trim().length > 0);\n return params.length ? params : undefined;\n}\n\nfunction normalizeProvision(value: unknown): OracleProvision | null {\n if (typeof value === \"string\") {\n return value.trim() ? { endpoint: value.trim() } : null;\n }\n\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return null;\n const record = value as Record<string, unknown>;\n if (typeof record.endpoint !== \"string\" || !record.endpoint.trim()) return null;\n\n return {\n endpoint: record.endpoint.trim(),\n headers: normalizeHeaders(record.headers),\n allowedParams: normalizeAllowedParams(record.allowedParams),\n };\n}\n\nexport function parseRuntimeOracleRegistry(raw: string | undefined): RuntimeOracleRegistry {\n if (!raw?.trim()) return {};\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (error) {\n throw new Error(\n `${FLAP_RUNTIME_ORACLE_REGISTRY_ENV} must be valid JSON: ${error instanceof Error ? error.message : String(error)}`,\n );\n }\n\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(`${FLAP_RUNTIME_ORACLE_REGISTRY_ENV} must be a JSON object keyed by oracle id.`);\n }\n\n return Object.fromEntries(\n Object.entries(parsed)\n .map(([oracleId, provision]) => [oracleId, normalizeProvision(provision)] as const)\n .filter((entry): entry is [string, OracleProvision] => Boolean(entry[1])),\n );\n}\n\nexport function resolveRuntimeOracleProvision(oracleId: string, registry: RuntimeOracleRegistry): OracleProvision | null {\n const provision = registry[oracleId];\n if (!provision) return null;\n return typeof provision === \"string\" ? { endpoint: provision } : provision;\n}\n\nexport function loadDefaultRuntimeOracle<T>(oracleId: string): T | null {\n if (oracleId === \"example-reward-oracle\") {\n return {\n rewardMultiplierBps: 175,\n timestamp: Math.floor(Date.now() / 1000),\n signature: DEFAULT_EXAMPLE_ORACLE_SIGNATURE,\n } as T;\n }\n\n return null;\n}\n\nexport async function loadRuntimeOracle<T>({\n oracleId,\n params,\n registry,\n fetchImpl,\n}: {\n oracleId: string;\n params?: Record<string, string>;\n registry: RuntimeOracleRegistry;\n fetchImpl?: typeof fetch;\n}): Promise<T | null> {\n const provision = resolveRuntimeOracleProvision(oracleId, registry);\n if (!provision) return null;\n return fetchProvisionedOracle<T>({\n provision,\n params,\n fetchImpl,\n });\n}\n"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as Address, A as ActionAvailabilityStage, T as TokenMarketPhase, h as FlapTokenInfo,
|
|
1
|
+
import { y as OracleReader, O as OracleProvision, a as Address, A as ActionAvailabilityStage, T as TokenMarketPhase, h as FlapTokenInfo, G as VaultHostContext, g as FlapTaxInfo, i as FlapVaultPortalInfo, F as FeeMode, J as VaultRenderSurface, I as VaultManifest, d as FlapFeeVaultInfo, M as ManifestBindingEntry } from './types-DzTX2u7q.mjs';
|
|
2
2
|
|
|
3
3
|
declare const standardErc20Abi: readonly [{
|
|
4
4
|
readonly type: "event";
|
|
@@ -142,12 +142,33 @@ declare function parseTokenAmount(value: string, decimals?: number): bigint;
|
|
|
142
142
|
declare function formatPercentBps(value?: bigint | number | null, precision?: number): string;
|
|
143
143
|
declare function formatCountdown(targetTimeMs?: number): string;
|
|
144
144
|
|
|
145
|
+
declare class OracleReadError extends Error {
|
|
146
|
+
status?: number;
|
|
147
|
+
constructor(message: string, status?: number);
|
|
148
|
+
}
|
|
149
|
+
declare function buildLocalOracleUrl(oracleId: string, params?: Record<string, string>, endpointBase?: string): string;
|
|
150
|
+
declare function fetchOracleJson<T>({ endpoint, params, fetchImpl, headers, }: {
|
|
151
|
+
endpoint: string;
|
|
152
|
+
params?: Record<string, string>;
|
|
153
|
+
fetchImpl?: typeof fetch;
|
|
154
|
+
headers?: HeadersInit;
|
|
155
|
+
}): Promise<T>;
|
|
156
|
+
declare function fetchProvisionedOracle<T>({ provision, params, fetchImpl, }: {
|
|
157
|
+
provision: string | OracleProvision;
|
|
158
|
+
params?: Record<string, string>;
|
|
159
|
+
fetchImpl?: typeof fetch;
|
|
160
|
+
}): Promise<T>;
|
|
161
|
+
declare function createLocalOracleReader(options?: {
|
|
162
|
+
endpointBase?: string;
|
|
163
|
+
fetchImpl?: typeof fetch;
|
|
164
|
+
}): OracleReader;
|
|
165
|
+
|
|
145
166
|
declare const ZERO_ADDRESS: Address;
|
|
146
167
|
type TupleLike = (Record<string, unknown> & readonly unknown[]) | Record<string, unknown> | readonly unknown[] | null | undefined;
|
|
147
168
|
interface VaultBindingPolicy {
|
|
148
169
|
name: string;
|
|
149
170
|
chainId: number;
|
|
150
|
-
factoryAddress
|
|
171
|
+
factoryAddress?: Address;
|
|
151
172
|
vaultAddresses?: Address[];
|
|
152
173
|
extra?: Record<string, unknown>;
|
|
153
174
|
isAiPowered?: boolean;
|
|
@@ -155,6 +176,7 @@ interface VaultBindingPolicy {
|
|
|
155
176
|
interface RuntimeMatchInput {
|
|
156
177
|
chainId?: number;
|
|
157
178
|
factoryAddress?: string | null;
|
|
179
|
+
vaultAddress?: string | null;
|
|
158
180
|
tokenAddress?: string | null;
|
|
159
181
|
}
|
|
160
182
|
interface CreateTaxInfoHostContextInput {
|
|
@@ -213,4 +235,4 @@ type TxErrorMessageMap = Partial<Record<TxErrorKind, string>>;
|
|
|
213
235
|
declare function getTxErrorKind(error: unknown): TxErrorKind;
|
|
214
236
|
declare function handleTxError(error: unknown, messages?: TxErrorMessageMap): string;
|
|
215
237
|
|
|
216
|
-
export {
|
|
238
|
+
export { resolveFeeMode as A, resolveManifestBinding as B, type CreateTaxInfoHostContextInput as C, resolveTaxInfoRenderSurface as D, resolveTokenMarketPhase as E, resolveVaultBinding as F, shortenAddress as G, standardErc20Abi as H, OracleReadError as O, type ResolveRenderSurfaceInput as R, type TaxVaultHostSnapshot as T, type VaultBindingPolicy as V, ZERO_ADDRESS as Z, type RuntimeMatchInput as a, type TxErrorKind as b, buildLocalOracleUrl as c, createLocalOracleReader as d, createTaxInfoHostContext as e, fetchOracleJson as f, fetchProvisionedOracle as g, formatCountdown as h, formatPercentBps as i, formatTokenAmount as j, getTupleField as k, getTxErrorKind as l, handleTxError as m, isActionAvailableForPhase as n, isCustomVaultTaxToken as o, isManifestRuntimeMatch as p, isSameAddress as q, isValidAddress as r, isVaultBindingMatch as s, normalizeAddress as t, parseFeeVaultInfo as u, parsePortalTokenInfo as v, parseTaxTokenInfo as w, parseTokenAmount as x, parseVaultPortalInfo as y, readTaxVaultHostContext as z };
|
|
@@ -148,6 +148,7 @@ interface VaultRuntimeExtraConfig extends Record<string, unknown> {
|
|
|
148
148
|
tokenUnavailable?: boolean;
|
|
149
149
|
tokenDetailHref?: string;
|
|
150
150
|
chainHref?: string;
|
|
151
|
+
/** Legacy preview-only fallback. Prefer runtime-level oracleReader provisioning. */
|
|
151
152
|
oracleEndpoints?: Record<string, string>;
|
|
152
153
|
hostRuntimeStatus?: HostRuntimeStatus;
|
|
153
154
|
hostRuntimePolicy?: HostRuntimePolicy;
|
|
@@ -156,9 +157,14 @@ interface VaultRuntimeExtraConfig extends Record<string, unknown> {
|
|
|
156
157
|
}
|
|
157
158
|
interface ManifestBindingEntry {
|
|
158
159
|
chainId: number;
|
|
159
|
-
factoryAddress
|
|
160
|
+
factoryAddress?: Address;
|
|
160
161
|
vaultAddresses?: Address[];
|
|
161
162
|
tokenAddresses?: Address[];
|
|
163
|
+
externalContracts?: ManifestExternalContract[];
|
|
164
|
+
}
|
|
165
|
+
interface ManifestExternalContract {
|
|
166
|
+
address: Address;
|
|
167
|
+
label: string;
|
|
162
168
|
}
|
|
163
169
|
interface VaultManifest {
|
|
164
170
|
artifactId: string;
|
|
@@ -188,6 +194,18 @@ interface VaultRuntimeContext {
|
|
|
188
194
|
interface VaultRuntimeContextOverrides extends Partial<Omit<VaultRuntimeContext, "manifest" | "extraConfig">> {
|
|
189
195
|
extraConfig?: VaultRuntimeExtraConfig;
|
|
190
196
|
}
|
|
197
|
+
interface OracleProvision {
|
|
198
|
+
endpoint: string;
|
|
199
|
+
headers?: Record<string, string>;
|
|
200
|
+
allowedParams?: string[];
|
|
201
|
+
}
|
|
202
|
+
type RuntimeOracleRegistry = Record<string, OracleProvision | string>;
|
|
203
|
+
interface OracleReadRequest {
|
|
204
|
+
oracleId: string;
|
|
205
|
+
params?: Record<string, string>;
|
|
206
|
+
context: VaultRuntimeContext;
|
|
207
|
+
}
|
|
208
|
+
type OracleReader = <T = unknown>(request: OracleReadRequest) => Promise<T>;
|
|
191
209
|
interface CreateVaultRuntimeContextInput {
|
|
192
210
|
manifest: VaultManifest;
|
|
193
211
|
connectedChainId?: number;
|
|
@@ -267,4 +285,4 @@ interface VaultComponentProps {
|
|
|
267
285
|
context?: VaultRuntimeContext;
|
|
268
286
|
}
|
|
269
287
|
|
|
270
|
-
export type { ActionAvailabilityStage as A,
|
|
288
|
+
export type { ActionAvailabilityStage as A, TokenRuntimeSnapshot as B, ContractReadRequest as C, TxReceipt as D, EndpointPolicy as E, FeeMode as F, VaultHostContext as G, HostRuntimeAddresses as H, VaultManifest as I, VaultRenderSurface as J, VaultRuntimeContext as K, VaultRuntimeContextOverrides as L, ManifestBindingEntry as M, VaultRuntimeExtraConfig as N, OracleProvision as O, PaymentToken as P, RuntimeOracleRegistry as R, SimulateResult as S, TokenMarketPhase as T, VaultComponentProps as V, Address as a, ContractWriteRequest as b, CreateVaultRuntimeContextInput as c, FlapFeeVaultInfo as d, FlapI18n as e, FlapNotify as f, FlapTaxInfo as g, FlapTokenInfo as h, FlapVaultPortalInfo as i, FlapVaultSdk as j, FlapWallet as k, HostRuntimeDataSource as l, HostRuntimeDegradeReason as m, HostRuntimeInput as n, HostRuntimePolicy as o, HostRuntimePresentationFetcher as p, HostRuntimePresentationRequest as q, HostRuntimeResult as r, HostRuntimeSources as s, HostRuntimeStatus as t, HostRuntimeWarning as u, HostTokenPresentation as v, ManifestExternalContract as w, OracleReadRequest as x, OracleReader as y, TokenMetadataSnapshot as z };
|
package/ui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/sdk/format.ts","../../src/ui/AddressLink.tsx","../../src/ui/utils.ts","../../src/ui/Alert.tsx","../../src/ui/Button.tsx","../../src/ui/Card.tsx","../../src/ui/Countdown.tsx","../../src/ui/DataRow.tsx","../../src/ui/DetailTile.tsx","../../src/ui/Input.tsx","../../src/ui/Metric.tsx","../../src/ui/StatusBadge.tsx","../../src/ui/TxButton.tsx","../../src/ui/VaultBanner.tsx"],"names":["React2","toneClass","React4"],"mappings":"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","file":"ui.js","sourcesContent":["import Decimal from \"decimal.js\";\nimport { formatUnits, parseUnits } from \"viem\";\n\nexport function shortenAddress(raw?: string, start = 6, end = 4) {\n if (!raw) return \"\";\n if (raw.length <= start + end) return raw;\n return `${raw.slice(0, start)}...${raw.slice(-end)}`;\n}\n\nexport function formatTokenAmount(value?: bigint | string | number | null, decimals = 18, precision = 4) {\n if (value === undefined || value === null) return \"-\";\n const raw = typeof value === \"bigint\" ? formatUnits(value, decimals) : String(value);\n return new Decimal(raw).toDecimalPlaces(precision, Decimal.ROUND_DOWN).toString();\n}\n\nexport function parseTokenAmount(value: string, decimals = 18) {\n if (!/^\\d*(\\.\\d*)?$/.test(value.trim())) {\n throw new Error(\"Invalid decimal amount.\");\n }\n return parseUnits(value || \"0\", decimals);\n}\n\nexport function formatPercentBps(value?: bigint | number | null, precision = 2) {\n if (value === undefined || value === null) return \"-\";\n return `${new Decimal(String(value)).div(100).toDecimalPlaces(precision).toString()}%`;\n}\n\nexport function formatCountdown(targetTimeMs?: number) {\n if (!targetTimeMs) return \"-\";\n const diff = Math.max(0, targetTimeMs - Date.now());\n const totalSeconds = Math.floor(diff / 1000);\n const hours = Math.floor(totalSeconds / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n if (hours > 0) return `${hours}h ${minutes}m ${seconds}s`;\n return `${minutes}m ${seconds}s`;\n}\n","import { ExternalLink } from \"lucide-react\";\nimport { shortenAddress } from \"@/src/sdk/format\";\n\ninterface AddressLinkProps {\n address?: string;\n explorerBaseUrl?: string;\n label?: string;\n}\n\nexport function AddressLink({ address, explorerBaseUrl, label }: AddressLinkProps) {\n if (!address) return <span>-</span>;\n const href = explorerBaseUrl ? `${explorerBaseUrl.replace(/\\/$/, \"\")}/address/${address}` : undefined;\n const content = (\n <span className=\"inline-flex min-w-0 items-center gap-1 text-primary\">\n <span className=\"truncate\">{label || shortenAddress(address)}</span>\n {href ? <ExternalLink className=\"h-3.5 w-3.5 shrink-0\" /> : null}\n </span>\n );\n return href ? (\n <a href={href} target=\"_blank\" rel=\"noreferrer\">\n {content}\n </a>\n ) : (\n content\n );\n}\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { AlertTriangle, CheckCircle2, Info } from \"lucide-react\";\nimport { ReactNode } from \"react\";\nimport { cn } from \"./utils\";\n\ntype AlertTone = \"info\" | \"success\" | \"warning\" | \"danger\";\n\nconst toneClass: Record<AlertTone, string> = {\n info: \"border-[#3f5f8f] bg-[#17243a] text-[#d8e2ef]\",\n success: \"border-[#35d39d]/35 bg-[#173c39] text-[#8ff4c8]\",\n warning: \"border-[#f2c94c]/35 bg-[#42381f] text-[#fff0b8]\",\n danger: \"border-[#ff6b6b]/35 bg-[#4a1f27] text-[#ffc4c4]\",\n};\n\nconst iconMap = {\n info: Info,\n success: CheckCircle2,\n warning: AlertTriangle,\n danger: AlertTriangle,\n};\n\nexport function Alert({ children, tone = \"info\", className }: { children: ReactNode; tone?: AlertTone; className?: string }) {\n const Icon = iconMap[tone];\n return (\n <div className={cn(\"flex gap-3 rounded-md border p-3 text-sm font-medium leading-6\", toneClass[tone], className)}>\n <Icon className=\"mt-0.5 h-4 w-4 shrink-0 opacity-90\" />\n <div className=\"min-w-0 break-words\">{children}</div>\n </div>\n );\n}\n","import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Loader2 } from \"lucide-react\";\nimport { cn } from \"./utils\";\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-semibold transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#4a90ff]/60 disabled:pointer-events-none disabled:opacity-50\",\n {\n variants: {\n variant: {\n default: \"border border-[#4a90ff]/60 bg-[#315fb5] text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.16)] hover:bg-[#3b70d6]\",\n secondary: \"border border-[#3a4d66] bg-[#304057] text-white hover:bg-[#3a4c65]\",\n outline: \"border border-[#3d6ba8] bg-[#17243a] text-[#d8e8ff] hover:border-[#559cff] hover:bg-[#1d3150]\",\n ghost: \"text-[#a8b5c7] hover:bg-[#304057] hover:text-white\",\n destructive: \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n },\n size: {\n default: \"h-10 px-4\",\n sm: \"h-8 px-3 text-xs\",\n lg: \"h-12 px-5\",\n icon: \"h-10 w-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n loading?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, loading = false, disabled, children, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n if (asChild) {\n return (\n <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props}>\n {children}\n </Comp>\n );\n }\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n disabled={disabled || loading}\n {...props}\n >\n {loading ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : null}\n {children}\n </Comp>\n );\n },\n);\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n","import * as React from \"react\";\nimport { cn } from \"./utils\";\n\nconst Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"rounded-lg border border-[#3a4d66] bg-[#1d2938] text-white shadow-panel shadow-black/30 backdrop-blur\",\n className,\n )}\n {...props}\n />\n));\nCard.displayName = \"Card\";\n\nconst CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"flex flex-col gap-1.5 p-5\", className)} {...props} />\n ),\n);\nCardHeader.displayName = \"CardHeader\";\n\nconst CardTitle = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(\n ({ className, ...props }, ref) => (\n <h3 ref={ref} className={cn(\"text-lg font-semibold leading-tight tracking-normal text-white\", className)} {...props} />\n ),\n);\nCardTitle.displayName = \"CardTitle\";\n\nconst CardDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(\n ({ className, ...props }, ref) => (\n <p ref={ref} className={cn(\"text-sm leading-6 text-[#a8b5c7]\", className)} {...props} />\n ),\n);\nCardDescription.displayName = \"CardDescription\";\n\nconst CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => <div ref={ref} className={cn(\"p-5 pt-0\", className)} {...props} />,\n);\nCardContent.displayName = \"CardContent\";\n\nexport { Card, CardContent, CardDescription, CardHeader, CardTitle };\n","import { useEffect, useMemo, useState } from \"react\";\n\nfunction formatMs(ms: number) {\n const safe = Math.max(0, ms);\n const totalSeconds = Math.floor(safe / 1000);\n const days = Math.floor(totalSeconds / 86400);\n const hours = Math.floor((totalSeconds % 86400) / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n if (days > 0) return `${days}d ${hours}h ${minutes}m`;\n if (hours > 0) return `${hours}h ${minutes}m ${seconds}s`;\n return `${minutes}m ${seconds}s`;\n}\n\nexport function Countdown({ targetTimeMs, fallback = \"-\" }: { targetTimeMs?: number; fallback?: string }) {\n const [now, setNow] = useState(() => Date.now());\n\n useEffect(() => {\n const timer = window.setInterval(() => setNow(Date.now()), 1000);\n return () => window.clearInterval(timer);\n }, []);\n\n const text = useMemo(() => {\n if (!targetTimeMs) return fallback;\n return formatMs(targetTimeMs - now);\n }, [fallback, now, targetTimeMs]);\n\n return <span>{text}</span>;\n}\n","import { ReactNode } from \"react\";\nimport { cn } from \"./utils\";\n\ninterface DataRowProps {\n label: ReactNode;\n value: ReactNode;\n detail?: ReactNode;\n className?: string;\n}\n\nexport function DataRow({ label, value, detail, className }: DataRowProps) {\n return (\n <div className={cn(\"flex items-start justify-between gap-4 border-b border-white/8 py-3 last:border-0\", className)}>\n <div className=\"min-w-0 text-sm text-white/54\">{label}</div>\n <div className=\"min-w-0 text-right\">\n <div className=\"break-words text-sm font-semibold text-white\">{value}</div>\n {detail ? <div className=\"mt-1 text-xs text-white/42\">{detail}</div> : null}\n </div>\n </div>\n );\n}\n","import { ReactNode } from \"react\";\nimport { cn } from \"./utils\";\n\ntype DetailTileTone = \"default\" | \"primary\" | \"success\" | \"warning\" | \"muted\";\n\nconst toneClass: Record<DetailTileTone, string> = {\n default: \"border-[#40536c] bg-[#304057]\",\n primary: \"border-[#3b82f6]/60 bg-[#17325a]\",\n success: \"border-[#35d39d]/40 bg-[#173c39]\",\n warning: \"border-[#f2c94c]/40 bg-[#42381f]\",\n muted: \"border-[#33445b] bg-[#172131]\",\n};\n\ninterface DetailTileProps {\n label: ReactNode;\n value: ReactNode;\n detail?: ReactNode;\n icon?: ReactNode;\n tone?: DetailTileTone;\n className?: string;\n valueClassName?: string;\n}\n\nexport function DetailTile({ label, value, detail, icon, tone = \"default\", className, valueClassName }: DetailTileProps) {\n return (\n <div className={cn(\"min-w-0 rounded-md border p-3\", toneClass[tone], className)}>\n <div className=\"flex min-w-0 items-center gap-2 text-xs font-medium text-[#a9b6c8]\">\n {icon ? <span className=\"shrink-0 text-[#8fb7ff]\">{icon}</span> : null}\n <span className=\"min-w-0 truncate\">{label}</span>\n </div>\n <div className={cn(\"mt-2 min-w-0 break-words text-base font-semibold leading-snug text-white\", valueClassName)}>\n {value}\n </div>\n {detail ? <div className=\"mt-1 min-w-0 break-words text-xs leading-5 text-[#8d9caf]\">{detail}</div> : null}\n </div>\n );\n}\n","import * as React from \"react\";\nimport { cn } from \"./utils\";\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(({ className, ...props }, ref) => (\n <input\n ref={ref}\n className={cn(\n \"flex h-11 w-full rounded-md border border-[#aebdd0] bg-[#101827] px-3 py-2 text-sm font-semibold text-white caret-white shadow-[inset_0_1px_0_rgba(255,255,255,0.05)] outline-none transition-colors selection:bg-[#4a90ff]/45 selection:text-white placeholder:text-[#7f8ca0] focus:border-[#64a7ff] focus:bg-[#132033] focus:ring-2 focus:ring-[#4a90ff]/30 disabled:cursor-not-allowed disabled:border-[#40536c] disabled:bg-[#1d2938] disabled:text-[#8d9caf] disabled:opacity-80\",\n className,\n )}\n {...props}\n />\n));\nInput.displayName = \"Input\";\n\nexport { Input };\n","import { ReactNode } from \"react\";\nimport { cn } from \"./utils\";\n\ntype MetricTone = \"default\" | \"primary\" | \"success\" | \"warning\" | \"muted\";\n\nconst toneClass: Record<MetricTone, string> = {\n default: \"border-[#40536c] bg-[#304057]\",\n primary: \"border-[#3b82f6]/55 bg-[#17325a]\",\n success: \"border-[#35d39d]/40 bg-[#173c39]\",\n warning: \"border-[#f2c94c]/40 bg-[#42381f]\",\n muted: \"border-[#33445b] bg-[#172131]\",\n};\n\nconst valueToneClass: Record<MetricTone, string> = {\n default: \"text-white\",\n primary: \"text-[#8fb7ff]\",\n success: \"text-[#6ff0bc]\",\n warning: \"text-[#ffe08a]\",\n muted: \"text-white\",\n};\n\ninterface MetricProps {\n label: ReactNode;\n value: ReactNode;\n hint?: ReactNode;\n tone?: MetricTone;\n className?: string;\n}\n\nexport function Metric({ label, value, hint, tone = \"default\", className }: MetricProps) {\n return (\n <div className={cn(\"rounded-md border p-3\", toneClass[tone], className)}>\n <div className=\"text-xs font-medium text-[#a9b6c8]\">{label}</div>\n <div className={cn(\"mt-2 break-words text-xl font-semibold tracking-normal\", valueToneClass[tone])}>{value}</div>\n {hint ? <div className=\"mt-1 text-xs text-[#d8e2ef]\">{hint}</div> : null}\n </div>\n );\n}\n","import { ReactNode } from \"react\";\nimport { cn } from \"./utils\";\n\nexport type StatusTone = \"neutral\" | \"success\" | \"warning\" | \"danger\";\n\nconst toneClass: Record<StatusTone, string> = {\n neutral: \"border-[#5d6f86] bg-[#2d3b50] text-[#d8e2ef]\",\n success: \"border-[#35d39d]/45 bg-[#176755]/55 text-[#78f2bf]\",\n warning: \"border-[#f2c94c]/45 bg-[#59451f]/55 text-[#ffe08a]\",\n danger: \"border-[#ff6b6b]/45 bg-[#5f2027]/55 text-[#ffb2b2]\",\n};\n\nexport function StatusBadge({ children, tone = \"neutral\" }: { children: ReactNode; tone?: StatusTone }) {\n return (\n <span className={cn(\"inline-flex items-center rounded-full border px-3 py-1 text-xs font-semibold leading-none\", toneClass[tone])}>\n {children}\n </span>\n );\n}\n","import { Button, type ButtonProps } from \"./Button\";\n\nexport type TxButtonState = \"idle\" | \"validating\" | \"approving\" | \"approval_confirming\" | \"simulating\" | \"writing\" | \"confirming\" | \"success\" | \"failed\";\n\nconst labels: Record<TxButtonState, string> = {\n idle: \"\",\n validating: \"Validating\",\n approving: \"Approving\",\n approval_confirming: \"Confirming approval\",\n simulating: \"Simulating\",\n writing: \"Sending\",\n confirming: \"Confirming\",\n success: \"Done\",\n failed: \"Retry\",\n};\n\ninterface TxButtonProps extends ButtonProps {\n state?: TxButtonState;\n idleLabel: string;\n}\n\nexport function TxButton({ state = \"idle\", idleLabel, children, ...props }: TxButtonProps) {\n const loading = [\"validating\", \"approving\", \"approval_confirming\", \"simulating\", \"writing\", \"confirming\"].includes(state);\n return (\n <Button loading={loading} {...props}>\n {children || labels[state] || idleLabel}\n </Button>\n );\n}\n","import { ShieldCheck } from \"lucide-react\";\nimport { ReactNode } from \"react\";\nimport { cn } from \"./utils\";\n\ninterface VaultBannerProps {\n title: ReactNode;\n description: ReactNode;\n badges?: ReactNode;\n meta?: ReactNode;\n action?: ReactNode;\n icon?: ReactNode;\n className?: string;\n}\n\nexport function VaultBanner({ title, description, badges, meta, action, icon, className }: VaultBannerProps) {\n return (\n <section\n className={cn(\n \"rounded-lg border border-[#3b82f6] bg-[#172a5a] p-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.08)]\",\n className,\n )}\n >\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"inline-flex h-4 w-4 shrink-0 items-center justify-center text-[#8fc8ff]\">\n {icon ?? <ShieldCheck className=\"h-4 w-4\" />}\n </span>\n <h3 className=\"min-w-0 text-base font-semibold leading-tight text-white\">{title}</h3>\n {badges}\n </div>\n <p className=\"mt-3 max-w-3xl text-sm font-medium leading-6 text-[#d8e2ef]\">{description}</p>\n {meta ? <div className=\"mt-2 text-xs font-medium leading-5 text-[#92a4bd]\">{meta}</div> : null}\n </div>\n {action ? <div className=\"shrink-0\">{action}</div> : null}\n </div>\n </section>\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/sdk/format.ts","../../src/ui/AddressLink.tsx","../../src/ui/utils.ts","../../src/ui/Alert.tsx","../../src/ui/Button.tsx","../../src/ui/Card.tsx","../../src/ui/Countdown.tsx","../../src/ui/DataRow.tsx","../../src/ui/DetailTile.tsx","../../src/ui/Input.tsx","../../src/ui/Metric.tsx","../../src/ui/StatusBadge.tsx","../../src/ui/TxButton.tsx","../../src/ui/VaultBanner.tsx"],"names":["React2","toneClass","React4"],"mappings":"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","file":"ui.js","sourcesContent":["import Decimal from \"decimal.js\";\nimport { formatUnits, parseUnits } from \"viem\";\n\nexport function shortenAddress(raw?: string, start = 6, end = 4) {\n if (!raw) return \"\";\n if (raw.length <= start + end) return raw;\n return `${raw.slice(0, start)}...${raw.slice(-end)}`;\n}\n\nexport function formatTokenAmount(value?: bigint | string | number | null, decimals = 18, precision = 4) {\n if (value === undefined || value === null) return \"-\";\n const raw = typeof value === \"bigint\" ? formatUnits(value, decimals) : String(value);\n return new Decimal(raw).toDecimalPlaces(precision, Decimal.ROUND_DOWN).toString();\n}\n\nexport function parseTokenAmount(value: string, decimals = 18) {\n if (!/^\\d*(\\.\\d*)?$/.test(value.trim())) {\n throw new Error(\"Invalid decimal amount.\");\n }\n return parseUnits(value || \"0\", decimals);\n}\n\nexport function formatPercentBps(value?: bigint | number | null, precision = 2) {\n if (value === undefined || value === null) return \"-\";\n return `${new Decimal(String(value)).div(100).toDecimalPlaces(precision).toString()}%`;\n}\n\nexport function formatCountdown(targetTimeMs?: number) {\n if (!targetTimeMs) return \"-\";\n const diff = Math.max(0, targetTimeMs - Date.now());\n const totalSeconds = Math.floor(diff / 1000);\n const days = Math.floor(totalSeconds / 86400);\n const hours = Math.floor((totalSeconds % 86400) / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n if (days > 0) return `${days}d ${hours}h ${minutes}m`;\n if (hours > 0) return `${hours}h ${minutes}m ${seconds}s`;\n return `${minutes}m ${seconds}s`;\n}\n","import { ExternalLink } from \"lucide-react\";\nimport { shortenAddress } from \"@/src/sdk/format\";\n\ninterface AddressLinkProps {\n address?: string;\n explorerBaseUrl?: string;\n label?: string;\n}\n\nexport function AddressLink({ address, explorerBaseUrl, label }: AddressLinkProps) {\n if (!address) return <span>-</span>;\n const href = explorerBaseUrl ? `${explorerBaseUrl.replace(/\\/$/, \"\")}/address/${address}` : undefined;\n const content = (\n <span className=\"inline-flex min-w-0 items-center gap-1 text-primary\">\n <span className=\"truncate\">{label || shortenAddress(address)}</span>\n {href ? <ExternalLink className=\"h-3.5 w-3.5 shrink-0\" /> : null}\n </span>\n );\n return href ? (\n <a href={href} target=\"_blank\" rel=\"noreferrer\">\n {content}\n </a>\n ) : (\n content\n );\n}\n","import { type ClassValue, clsx } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs));\n}\n","import { AlertTriangle, CheckCircle2, Info } from \"lucide-react\";\nimport { ReactNode } from \"react\";\nimport { cn } from \"./utils\";\n\ntype AlertTone = \"info\" | \"success\" | \"warning\" | \"danger\";\n\nconst toneClass: Record<AlertTone, string> = {\n info: \"border-[#3f5f8f] bg-[#17243a] text-[#d8e2ef]\",\n success: \"border-[#35d39d]/35 bg-[#173c39] text-[#8ff4c8]\",\n warning: \"border-[#f2c94c]/35 bg-[#42381f] text-[#fff0b8]\",\n danger: \"border-[#ff6b6b]/35 bg-[#4a1f27] text-[#ffc4c4]\",\n};\n\nconst iconMap = {\n info: Info,\n success: CheckCircle2,\n warning: AlertTriangle,\n danger: AlertTriangle,\n};\n\nexport function Alert({ children, tone = \"info\", className }: { children: ReactNode; tone?: AlertTone; className?: string }) {\n const Icon = iconMap[tone];\n return (\n <div className={cn(\"flex gap-3 rounded-md border p-3 text-sm font-medium leading-6\", toneClass[tone], className)}>\n <Icon className=\"mt-0.5 h-4 w-4 shrink-0 opacity-90\" />\n <div className=\"min-w-0 break-words\">{children}</div>\n </div>\n );\n}\n","import * as React from \"react\";\nimport { Slot } from \"@radix-ui/react-slot\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { Loader2 } from \"lucide-react\";\nimport { cn } from \"./utils\";\n\nconst buttonVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-semibold transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#4a90ff]/60 disabled:pointer-events-none disabled:opacity-50\",\n {\n variants: {\n variant: {\n default: \"border border-[#4a90ff]/60 bg-[#315fb5] text-white shadow-[inset_0_1px_0_rgba(255,255,255,0.16)] hover:bg-[#3b70d6]\",\n secondary: \"border border-[#3a4d66] bg-[#304057] text-white hover:bg-[#3a4c65]\",\n outline: \"border border-[#3d6ba8] bg-[#17243a] text-[#d8e8ff] hover:border-[#559cff] hover:bg-[#1d3150]\",\n ghost: \"text-[#a8b5c7] hover:bg-[#304057] hover:text-white\",\n destructive: \"bg-destructive text-destructive-foreground hover:bg-destructive/90\",\n },\n size: {\n default: \"h-10 px-4\",\n sm: \"h-8 px-3 text-xs\",\n lg: \"h-12 px-5\",\n icon: \"h-10 w-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n },\n);\n\nexport interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {\n asChild?: boolean;\n loading?: boolean;\n}\n\nconst Button = React.forwardRef<HTMLButtonElement, ButtonProps>(\n ({ className, variant, size, asChild = false, loading = false, disabled, children, ...props }, ref) => {\n const Comp = asChild ? Slot : \"button\";\n if (asChild) {\n return (\n <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props}>\n {children}\n </Comp>\n );\n }\n return (\n <Comp\n className={cn(buttonVariants({ variant, size, className }))}\n ref={ref}\n disabled={disabled || loading}\n {...props}\n >\n {loading ? <Loader2 className=\"h-4 w-4 animate-spin\" /> : null}\n {children}\n </Comp>\n );\n },\n);\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants };\n","import * as React from \"react\";\nimport { cn } from \"./utils\";\n\nconst Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n \"rounded-lg border border-[#3a4d66] bg-[#1d2938] text-white shadow-panel shadow-black/30 backdrop-blur\",\n className,\n )}\n {...props}\n />\n));\nCard.displayName = \"Card\";\n\nconst CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => (\n <div ref={ref} className={cn(\"flex flex-col gap-1.5 p-5\", className)} {...props} />\n ),\n);\nCardHeader.displayName = \"CardHeader\";\n\nconst CardTitle = React.forwardRef<HTMLHeadingElement, React.HTMLAttributes<HTMLHeadingElement>>(\n ({ className, ...props }, ref) => (\n <h3 ref={ref} className={cn(\"text-lg font-semibold leading-tight tracking-normal text-white\", className)} {...props} />\n ),\n);\nCardTitle.displayName = \"CardTitle\";\n\nconst CardDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(\n ({ className, ...props }, ref) => (\n <p ref={ref} className={cn(\"text-sm leading-6 text-[#a8b5c7]\", className)} {...props} />\n ),\n);\nCardDescription.displayName = \"CardDescription\";\n\nconst CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(\n ({ className, ...props }, ref) => <div ref={ref} className={cn(\"p-5 pt-0\", className)} {...props} />,\n);\nCardContent.displayName = \"CardContent\";\n\nexport { Card, CardContent, CardDescription, CardHeader, CardTitle };\n","import { useEffect, useMemo, useState } from \"react\";\n\nfunction formatMs(ms: number) {\n const safe = Math.max(0, ms);\n const totalSeconds = Math.floor(safe / 1000);\n const days = Math.floor(totalSeconds / 86400);\n const hours = Math.floor((totalSeconds % 86400) / 3600);\n const minutes = Math.floor((totalSeconds % 3600) / 60);\n const seconds = totalSeconds % 60;\n if (days > 0) return `${days}d ${hours}h ${minutes}m`;\n if (hours > 0) return `${hours}h ${minutes}m ${seconds}s`;\n return `${minutes}m ${seconds}s`;\n}\n\nexport function Countdown({ targetTimeMs, fallback = \"-\" }: { targetTimeMs?: number; fallback?: string }) {\n const [now, setNow] = useState(() => Date.now());\n\n useEffect(() => {\n const timer = window.setInterval(() => setNow(Date.now()), 1000);\n return () => window.clearInterval(timer);\n }, []);\n\n const text = useMemo(() => {\n if (!targetTimeMs) return fallback;\n return formatMs(targetTimeMs - now);\n }, [fallback, now, targetTimeMs]);\n\n return <span>{text}</span>;\n}\n","import { ReactNode } from \"react\";\nimport { cn } from \"./utils\";\n\ninterface DataRowProps {\n label: ReactNode;\n value: ReactNode;\n detail?: ReactNode;\n className?: string;\n}\n\nexport function DataRow({ label, value, detail, className }: DataRowProps) {\n return (\n <div className={cn(\"flex items-start justify-between gap-4 border-b border-white/8 py-3 last:border-0\", className)}>\n <div className=\"min-w-0 text-sm text-white/54\">{label}</div>\n <div className=\"min-w-0 text-right\">\n <div className=\"break-words text-sm font-semibold text-white\">{value}</div>\n {detail ? <div className=\"mt-1 text-xs text-white/42\">{detail}</div> : null}\n </div>\n </div>\n );\n}\n","import { ReactNode } from \"react\";\nimport { cn } from \"./utils\";\n\ntype DetailTileTone = \"default\" | \"primary\" | \"success\" | \"warning\" | \"muted\";\n\nconst toneClass: Record<DetailTileTone, string> = {\n default: \"border-[#40536c] bg-[#304057]\",\n primary: \"border-[#3b82f6]/60 bg-[#17325a]\",\n success: \"border-[#35d39d]/40 bg-[#173c39]\",\n warning: \"border-[#f2c94c]/40 bg-[#42381f]\",\n muted: \"border-[#33445b] bg-[#172131]\",\n};\n\ninterface DetailTileProps {\n label: ReactNode;\n value: ReactNode;\n detail?: ReactNode;\n icon?: ReactNode;\n tone?: DetailTileTone;\n className?: string;\n valueClassName?: string;\n}\n\nexport function DetailTile({ label, value, detail, icon, tone = \"default\", className, valueClassName }: DetailTileProps) {\n return (\n <div className={cn(\"min-w-0 rounded-md border p-3\", toneClass[tone], className)}>\n <div className=\"flex min-w-0 items-center gap-2 text-xs font-medium text-[#a9b6c8]\">\n {icon ? <span className=\"shrink-0 text-[#8fb7ff]\">{icon}</span> : null}\n <span className=\"min-w-0 truncate\">{label}</span>\n </div>\n <div className={cn(\"mt-2 min-w-0 break-words text-base font-semibold leading-snug text-white\", valueClassName)}>\n {value}\n </div>\n {detail ? <div className=\"mt-1 min-w-0 break-words text-xs leading-5 text-[#8d9caf]\">{detail}</div> : null}\n </div>\n );\n}\n","import * as React from \"react\";\nimport { cn } from \"./utils\";\n\nexport interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}\n\nconst Input = React.forwardRef<HTMLInputElement, InputProps>(({ className, ...props }, ref) => (\n <input\n ref={ref}\n className={cn(\n \"flex h-11 w-full rounded-md border border-[#aebdd0] bg-[#101827] px-3 py-2 text-sm font-semibold text-white caret-white shadow-[inset_0_1px_0_rgba(255,255,255,0.05)] outline-none transition-colors selection:bg-[#4a90ff]/45 selection:text-white placeholder:text-[#7f8ca0] focus:border-[#64a7ff] focus:bg-[#132033] focus:ring-2 focus:ring-[#4a90ff]/30 disabled:cursor-not-allowed disabled:border-[#40536c] disabled:bg-[#1d2938] disabled:text-[#8d9caf] disabled:opacity-80\",\n className,\n )}\n {...props}\n />\n));\nInput.displayName = \"Input\";\n\nexport { Input };\n","import { ReactNode } from \"react\";\nimport { cn } from \"./utils\";\n\ntype MetricTone = \"default\" | \"primary\" | \"success\" | \"warning\" | \"muted\";\n\nconst toneClass: Record<MetricTone, string> = {\n default: \"border-[#40536c] bg-[#304057]\",\n primary: \"border-[#3b82f6]/55 bg-[#17325a]\",\n success: \"border-[#35d39d]/40 bg-[#173c39]\",\n warning: \"border-[#f2c94c]/40 bg-[#42381f]\",\n muted: \"border-[#33445b] bg-[#172131]\",\n};\n\nconst valueToneClass: Record<MetricTone, string> = {\n default: \"text-white\",\n primary: \"text-[#8fb7ff]\",\n success: \"text-[#6ff0bc]\",\n warning: \"text-[#ffe08a]\",\n muted: \"text-white\",\n};\n\ninterface MetricProps {\n label: ReactNode;\n value: ReactNode;\n hint?: ReactNode;\n tone?: MetricTone;\n className?: string;\n}\n\nexport function Metric({ label, value, hint, tone = \"default\", className }: MetricProps) {\n return (\n <div className={cn(\"rounded-md border p-3\", toneClass[tone], className)}>\n <div className=\"text-xs font-medium text-[#a9b6c8]\">{label}</div>\n <div className={cn(\"mt-2 break-words text-xl font-semibold tracking-normal\", valueToneClass[tone])}>{value}</div>\n {hint ? <div className=\"mt-1 text-xs text-[#d8e2ef]\">{hint}</div> : null}\n </div>\n );\n}\n","import { ReactNode } from \"react\";\nimport { cn } from \"./utils\";\n\nexport type StatusTone = \"neutral\" | \"success\" | \"warning\" | \"danger\";\n\nconst toneClass: Record<StatusTone, string> = {\n neutral: \"border-[#5d6f86] bg-[#2d3b50] text-[#d8e2ef]\",\n success: \"border-[#35d39d]/45 bg-[#176755]/55 text-[#78f2bf]\",\n warning: \"border-[#f2c94c]/45 bg-[#59451f]/55 text-[#ffe08a]\",\n danger: \"border-[#ff6b6b]/45 bg-[#5f2027]/55 text-[#ffb2b2]\",\n};\n\nexport function StatusBadge({ children, tone = \"neutral\" }: { children: ReactNode; tone?: StatusTone }) {\n return (\n <span className={cn(\"inline-flex items-center rounded-full border px-3 py-1 text-xs font-semibold leading-none\", toneClass[tone])}>\n {children}\n </span>\n );\n}\n","import { Button, type ButtonProps } from \"./Button\";\n\nexport type TxButtonState = \"idle\" | \"validating\" | \"approving\" | \"approval_confirming\" | \"simulating\" | \"writing\" | \"confirming\" | \"success\" | \"failed\";\n\nconst labels: Record<TxButtonState, string> = {\n idle: \"\",\n validating: \"Validating\",\n approving: \"Approving\",\n approval_confirming: \"Confirming approval\",\n simulating: \"Simulating\",\n writing: \"Sending\",\n confirming: \"Confirming\",\n success: \"Done\",\n failed: \"Retry\",\n};\n\ninterface TxButtonProps extends ButtonProps {\n state?: TxButtonState;\n idleLabel: string;\n}\n\nexport function TxButton({ state = \"idle\", idleLabel, children, ...props }: TxButtonProps) {\n const loading = [\"validating\", \"approving\", \"approval_confirming\", \"simulating\", \"writing\", \"confirming\"].includes(state);\n return (\n <Button loading={loading} {...props}>\n {children || labels[state] || idleLabel}\n </Button>\n );\n}\n","import { ShieldCheck } from \"lucide-react\";\nimport { ReactNode } from \"react\";\nimport { cn } from \"./utils\";\n\ninterface VaultBannerProps {\n title: ReactNode;\n description: ReactNode;\n badges?: ReactNode;\n meta?: ReactNode;\n action?: ReactNode;\n icon?: ReactNode;\n className?: string;\n}\n\nexport function VaultBanner({ title, description, badges, meta, action, icon, className }: VaultBannerProps) {\n return (\n <section\n className={cn(\n \"rounded-lg border border-[#3b82f6] bg-[#172a5a] p-4 shadow-[inset_0_1px_0_rgba(255,255,255,0.08)]\",\n className,\n )}\n >\n <div className=\"flex flex-col gap-4 sm:flex-row sm:items-start sm:justify-between\">\n <div className=\"min-w-0\">\n <div className=\"flex flex-wrap items-center gap-3\">\n <span className=\"inline-flex h-4 w-4 shrink-0 items-center justify-center text-[#8fc8ff]\">\n {icon ?? <ShieldCheck className=\"h-4 w-4\" />}\n </span>\n <h3 className=\"min-w-0 text-base font-semibold leading-tight text-white\">{title}</h3>\n {badges}\n </div>\n <p className=\"mt-3 max-w-3xl text-sm font-medium leading-6 text-[#d8e2ef]\">{description}</p>\n {meta ? <div className=\"mt-2 text-xs font-medium leading-5 text-[#92a4bd]\">{meta}</div> : null}\n </div>\n {action ? <div className=\"shrink-0\">{action}</div> : null}\n </div>\n </section>\n );\n}\n"]}
|