@flapsdk/vault-runtime 0.1.0
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 +14 -0
- package/host.d.mts +18 -0
- package/host.js +871 -0
- package/host.js.map +1 -0
- package/hostRuntimeConfig-BOEJo2nq.d.mts +14 -0
- package/package.json +49 -0
- package/runtime-contract.json +27 -0
- package/sdk.d.mts +24 -0
- package/sdk.js +571 -0
- package/sdk.js.map +1 -0
- package/server.d.mts +26 -0
- package/server.js +200 -0
- package/server.js.map +1 -0
- package/txError-1lPZHdqI.d.mts +216 -0
- package/types-CX7pLmiT.d.mts +270 -0
- package/ui.d.mts +99 -0
- package/ui.js +232 -0
- package/ui.js.map +1 -0
package/host.js
ADDED
|
@@ -0,0 +1,871 @@
|
|
|
1
|
+
import { erc20Abi, formatUnits, parseUnits } from 'viem';
|
|
2
|
+
export { erc20Abi } from 'viem';
|
|
3
|
+
import Decimal from 'decimal.js';
|
|
4
|
+
|
|
5
|
+
// src/sdk/erc20.ts
|
|
6
|
+
var standardErc20Abi = erc20Abi;
|
|
7
|
+
function shortenAddress(raw, start = 6, end = 4) {
|
|
8
|
+
if (!raw) return "";
|
|
9
|
+
if (raw.length <= start + end) return raw;
|
|
10
|
+
return `${raw.slice(0, start)}...${raw.slice(-end)}`;
|
|
11
|
+
}
|
|
12
|
+
function formatTokenAmount(value, decimals = 18, precision = 4) {
|
|
13
|
+
if (value === void 0 || value === null) return "-";
|
|
14
|
+
const raw = typeof value === "bigint" ? formatUnits(value, decimals) : String(value);
|
|
15
|
+
return new Decimal(raw).toDecimalPlaces(precision, Decimal.ROUND_DOWN).toString();
|
|
16
|
+
}
|
|
17
|
+
function parseTokenAmount(value, decimals = 18) {
|
|
18
|
+
if (!/^\d*(\.\d*)?$/.test(value.trim())) {
|
|
19
|
+
throw new Error("Invalid decimal amount.");
|
|
20
|
+
}
|
|
21
|
+
return parseUnits(value || "0", decimals);
|
|
22
|
+
}
|
|
23
|
+
function formatPercentBps(value, precision = 2) {
|
|
24
|
+
if (value === void 0 || value === null) return "-";
|
|
25
|
+
return `${new Decimal(String(value)).div(100).toDecimalPlaces(precision).toString()}%`;
|
|
26
|
+
}
|
|
27
|
+
function formatCountdown(targetTimeMs) {
|
|
28
|
+
if (!targetTimeMs) return "-";
|
|
29
|
+
const diff = Math.max(0, targetTimeMs - Date.now());
|
|
30
|
+
const totalSeconds = Math.floor(diff / 1e3);
|
|
31
|
+
const hours = Math.floor(totalSeconds / 3600);
|
|
32
|
+
const minutes = Math.floor(totalSeconds % 3600 / 60);
|
|
33
|
+
const seconds = totalSeconds % 60;
|
|
34
|
+
if (hours > 0) return `${hours}h ${minutes}m ${seconds}s`;
|
|
35
|
+
return `${minutes}m ${seconds}s`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/sdk/hostRuntimeConfig.ts
|
|
39
|
+
var taxVaultHostChains = {
|
|
40
|
+
56: {
|
|
41
|
+
portal: "0xe2ce6ab80874fa9fa2aae65d277dd6b8e65c9de0",
|
|
42
|
+
taxTokenHelperAddress: "0x53841c73217735F37BC1775538b03b23feFD8346",
|
|
43
|
+
vaultPortal: "0x90497450f2a706f1951b5bdda52B4E5d16f34C06",
|
|
44
|
+
wrappedNativeTokenAddress: "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c",
|
|
45
|
+
giftVaultFactory: "0x025549F52B03cF36f9e1a337c02d3AA7Af66ab32",
|
|
46
|
+
hostChainSlug: "bnb",
|
|
47
|
+
ipfsGateway: "https://gateway.pinata.cloud"
|
|
48
|
+
},
|
|
49
|
+
97: {
|
|
50
|
+
portal: "0x5bEacaF7ABCbB3aB280e80D007FD31fcE26510e9",
|
|
51
|
+
taxTokenHelperAddress: "0xD64441e5FcD02D342B8cf6eBA10Ef6E40d0dA90f",
|
|
52
|
+
vaultPortal: "0x027e3704fC5C16522e9393d04C60A3ac5c0d775f",
|
|
53
|
+
wrappedNativeTokenAddress: "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd",
|
|
54
|
+
giftVaultFactory: "0xa02DA44D67DB6D692efa7f751b5952bd670d5326",
|
|
55
|
+
hostChainSlug: "bnb-testnet",
|
|
56
|
+
ipfsGateway: "https://gateway.pinata.cloud"
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
function getTaxVaultHostChainConfig(chainId) {
|
|
60
|
+
return taxVaultHostChains[chainId];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/sdk/taxInfo.ts
|
|
64
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
65
|
+
function getTupleField(data, name, index) {
|
|
66
|
+
if (!data) return void 0;
|
|
67
|
+
const record = data;
|
|
68
|
+
const tuple = data;
|
|
69
|
+
return record[name] ?? tuple[index];
|
|
70
|
+
}
|
|
71
|
+
function isValidAddress(value) {
|
|
72
|
+
return Boolean(value && /^0x[a-fA-F0-9]{40}$/.test(value));
|
|
73
|
+
}
|
|
74
|
+
function normalizeAddress(value) {
|
|
75
|
+
return isValidAddress(value) ? value : void 0;
|
|
76
|
+
}
|
|
77
|
+
function isSameAddress(a, b) {
|
|
78
|
+
return Boolean(a && b && a.toLowerCase() === b.toLowerCase());
|
|
79
|
+
}
|
|
80
|
+
function toNumber(value, fallback = 0) {
|
|
81
|
+
if (typeof value === "bigint") return Number(value);
|
|
82
|
+
if (typeof value === "number") return Number.isFinite(value) ? value : fallback;
|
|
83
|
+
if (typeof value === "string" && value.trim()) {
|
|
84
|
+
const parsed = Number(value);
|
|
85
|
+
return Number.isFinite(parsed) ? parsed : fallback;
|
|
86
|
+
}
|
|
87
|
+
return fallback;
|
|
88
|
+
}
|
|
89
|
+
function toBigInt(value, fallback = 0n) {
|
|
90
|
+
if (typeof value === "bigint") return value;
|
|
91
|
+
if (typeof value === "number" && Number.isFinite(value)) return BigInt(Math.trunc(value));
|
|
92
|
+
if (typeof value === "string" && value.trim()) {
|
|
93
|
+
try {
|
|
94
|
+
return BigInt(value);
|
|
95
|
+
} catch {
|
|
96
|
+
return fallback;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return fallback;
|
|
100
|
+
}
|
|
101
|
+
function toBooleanOrNull(value) {
|
|
102
|
+
if (typeof value === "boolean") return value;
|
|
103
|
+
if (value === null || value === void 0) return null;
|
|
104
|
+
return Boolean(value);
|
|
105
|
+
}
|
|
106
|
+
function toAddressOrNull(value) {
|
|
107
|
+
return typeof value === "string" && isValidAddress(value) ? value : null;
|
|
108
|
+
}
|
|
109
|
+
function toStringOrUndefined(value) {
|
|
110
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
111
|
+
}
|
|
112
|
+
function parsePortalTokenInfo(tokenData) {
|
|
113
|
+
if (!tokenData) return null;
|
|
114
|
+
const status = toNumber(getTupleField(tokenData, "status", 0));
|
|
115
|
+
const taxRateRaw = toBigInt(getTupleField(tokenData, "taxRate", 12));
|
|
116
|
+
const quoteTokenAddress = toAddressOrNull(getTupleField(tokenData, "quoteTokenAddress", 9)) ?? ZERO_ADDRESS;
|
|
117
|
+
return {
|
|
118
|
+
exists: status !== 0,
|
|
119
|
+
isTaxToken: taxRateRaw > 0n,
|
|
120
|
+
taxRate: Number(taxRateRaw),
|
|
121
|
+
taxRateRaw,
|
|
122
|
+
quoteTokenAddress,
|
|
123
|
+
status,
|
|
124
|
+
tokenVersion: toNumber(getTupleField(tokenData, "tokenVersion", 4))
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function parseFeeVaultInfo(vaultInfo) {
|
|
128
|
+
if (!vaultInfo) return null;
|
|
129
|
+
return {
|
|
130
|
+
addr: toAddressOrNull(getTupleField(vaultInfo, "addr", 0)),
|
|
131
|
+
factory: toAddressOrNull(getTupleField(vaultInfo, "factory", 1)),
|
|
132
|
+
riskLevel: toNumber(getTupleField(vaultInfo, "riskLevel", 2)),
|
|
133
|
+
isOfficialVault: toBooleanOrNull(getTupleField(vaultInfo, "isOfficialVault", 3)),
|
|
134
|
+
isVault: toBooleanOrNull(getTupleField(vaultInfo, "isVault", 4)),
|
|
135
|
+
isAIConsumer: toBooleanOrNull(getTupleField(vaultInfo, "isAIConsumer", 5))
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function parseTaxTokenInfo(taxInfo, taxInfoV2, options = {}) {
|
|
139
|
+
if (!taxInfo) return null;
|
|
140
|
+
const quoteToken = toAddressOrNull(getTupleField(taxInfo, "quoteToken", 11)) ?? ZERO_ADDRESS;
|
|
141
|
+
const rawDividendToken = toAddressOrNull(getTupleField(taxInfoV2, "dividendToken", 11)) ?? quoteToken;
|
|
142
|
+
const dividendToken = quoteToken === ZERO_ADDRESS && rawDividendToken === ZERO_ADDRESS && options.wrappedNativeTokenAddress ? options.wrappedNativeTokenAddress : rawDividendToken;
|
|
143
|
+
return {
|
|
144
|
+
marketBps: toNumber(getTupleField(taxInfo, "marketBps", 0)),
|
|
145
|
+
deflationBps: toNumber(getTupleField(taxInfo, "deflationBps", 1)),
|
|
146
|
+
lpBps: toNumber(getTupleField(taxInfo, "lpBps", 2)),
|
|
147
|
+
dividendBps: toNumber(getTupleField(taxInfo, "dividendBps", 3)),
|
|
148
|
+
feeRate: toNumber(getTupleField(taxInfo, "feeRate", 4)),
|
|
149
|
+
buyTaxRate: taxInfoV2 ? toNumber(getTupleField(taxInfoV2, "buyTaxRate", 4)) : void 0,
|
|
150
|
+
sellTaxRate: taxInfoV2 ? toNumber(getTupleField(taxInfoV2, "sellTaxRate", 5)) : void 0,
|
|
151
|
+
burntTokenAmount: toBigInt(getTupleField(taxInfo, "burntTokenAmount", 5)),
|
|
152
|
+
totalQuoteSentToDividend: toBigInt(getTupleField(taxInfo, "totalQuoteSentToDividend", 6)),
|
|
153
|
+
totalQuoteAddedToLiquidity: toBigInt(getTupleField(taxInfo, "totalQuoteAddedToLiquidity", 7)),
|
|
154
|
+
totalTokenAddedToLiquidity: toBigInt(getTupleField(taxInfo, "totalTokenAddedToLiquidity", 8)),
|
|
155
|
+
totalQuoteSentToMarketing: toBigInt(getTupleField(taxInfo, "totalQuoteSentToMarketing", 9)),
|
|
156
|
+
marketingWallet: toAddressOrNull(getTupleField(taxInfo, "marketingWallet", 10)) ?? ZERO_ADDRESS,
|
|
157
|
+
dividendToken,
|
|
158
|
+
quoteToken,
|
|
159
|
+
minimumShareBalance: toBigInt(getTupleField(taxInfo, "minimumShareBalance", 12)),
|
|
160
|
+
vaultInfo: parseFeeVaultInfo(getTupleField(taxInfoV2, "vaultInfo", 14))
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
function parseVaultPortalInfo(vaultData) {
|
|
164
|
+
if (!vaultData) return null;
|
|
165
|
+
const found = Boolean(getTupleField(vaultData, "found", 0));
|
|
166
|
+
const info = getTupleField(vaultData, "info", 1);
|
|
167
|
+
if (!found || !info) return { found: false };
|
|
168
|
+
return {
|
|
169
|
+
found: true,
|
|
170
|
+
vault: toAddressOrNull(getTupleField(info, "vault", 0)) ?? ZERO_ADDRESS,
|
|
171
|
+
vaultFactory: toAddressOrNull(getTupleField(info, "vaultFactory", 1)) ?? ZERO_ADDRESS,
|
|
172
|
+
description: toStringOrUndefined(getTupleField(info, "description", 2)),
|
|
173
|
+
isOfficial: Boolean(getTupleField(info, "isOfficial", 3)),
|
|
174
|
+
riskLevel: toNumber(getTupleField(info, "riskLevel", 4))
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function resolveManifestBinding(manifest, input) {
|
|
178
|
+
const bindings = manifest.match.bindings;
|
|
179
|
+
if (!bindings.length) return null;
|
|
180
|
+
const resolveUnique = (candidates) => {
|
|
181
|
+
if (candidates.length === 1) return candidates[0];
|
|
182
|
+
return null;
|
|
183
|
+
};
|
|
184
|
+
if (input.chainId && input.factoryAddress) {
|
|
185
|
+
return resolveUnique(bindings.filter((binding) => binding.chainId === input.chainId && isSameAddress(binding.factoryAddress, input.factoryAddress)));
|
|
186
|
+
}
|
|
187
|
+
if (input.chainId) {
|
|
188
|
+
return resolveUnique(bindings.filter((binding) => binding.chainId === input.chainId));
|
|
189
|
+
}
|
|
190
|
+
if (input.factoryAddress) {
|
|
191
|
+
return resolveUnique(bindings.filter((binding) => isSameAddress(binding.factoryAddress, input.factoryAddress)));
|
|
192
|
+
}
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
function isManifestRuntimeMatch(manifest, input) {
|
|
196
|
+
if (!input.chainId || !input.factoryAddress) return false;
|
|
197
|
+
const matchingBinding = resolveManifestBinding(manifest, input);
|
|
198
|
+
if (!matchingBinding) return false;
|
|
199
|
+
return matchingBinding.chainId === input.chainId && isSameAddress(matchingBinding.factoryAddress, input.factoryAddress);
|
|
200
|
+
}
|
|
201
|
+
function isVaultBindingMatch(binding, input) {
|
|
202
|
+
if (!input.chainId || binding.chainId !== input.chainId) return false;
|
|
203
|
+
if (!input.factoryAddress || !isSameAddress(binding.factoryAddress, input.factoryAddress)) return false;
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
function resolveVaultBinding(bindings, input) {
|
|
207
|
+
return bindings.find((binding) => isVaultBindingMatch(binding, input)) ?? null;
|
|
208
|
+
}
|
|
209
|
+
function resolveFeeMode(taxInfo, giftVaultFactory) {
|
|
210
|
+
if (!taxInfo) return "unknown";
|
|
211
|
+
const marketBps = toNumber(getTupleField(taxInfo, "marketBps", 0));
|
|
212
|
+
const dividendBps = toNumber(getTupleField(taxInfo, "dividendBps", 3));
|
|
213
|
+
if (dividendBps > 0) return "holder";
|
|
214
|
+
if (marketBps <= 0) return "unknown";
|
|
215
|
+
const parsedVaultInfo = "vaultInfo" in Object(taxInfo) ? taxInfo.vaultInfo : parseFeeVaultInfo(getTupleField(taxInfo, "vaultInfo", 14));
|
|
216
|
+
if (parsedVaultInfo?.isVault === true) {
|
|
217
|
+
return isSameAddress(parsedVaultInfo.factory, giftVaultFactory) ? "gift" : "unknown";
|
|
218
|
+
}
|
|
219
|
+
return "creator";
|
|
220
|
+
}
|
|
221
|
+
function resolveTaxInfoRenderSurface({
|
|
222
|
+
tokenInfo,
|
|
223
|
+
taxInfo,
|
|
224
|
+
hasTaxVaults = false,
|
|
225
|
+
isNonTaxFeeToken = false
|
|
226
|
+
}) {
|
|
227
|
+
if (!tokenInfo?.exists) return "unavailable";
|
|
228
|
+
if (!tokenInfo.isTaxToken) return isNonTaxFeeToken ? "feeinfo" : "unavailable";
|
|
229
|
+
if (taxInfo?.marketBps === 1e4 && hasTaxVaults) return "vault-taxinfo";
|
|
230
|
+
return "standard-taxinfo";
|
|
231
|
+
}
|
|
232
|
+
function resolveTokenMarketPhase(tokenInfo) {
|
|
233
|
+
if (!tokenInfo?.exists) return "unknown";
|
|
234
|
+
return tokenInfo.status >= 2 ? "dex-listed" : "internal-market";
|
|
235
|
+
}
|
|
236
|
+
function isCustomVaultTaxToken(tokenInfo) {
|
|
237
|
+
return Boolean(tokenInfo?.exists && tokenInfo.isTaxToken);
|
|
238
|
+
}
|
|
239
|
+
function isActionAvailableForPhase(stage, marketPhase = "unknown") {
|
|
240
|
+
if (stage === "read-only") return false;
|
|
241
|
+
if (stage === "both") return true;
|
|
242
|
+
if (marketPhase === "unknown") return false;
|
|
243
|
+
return stage === marketPhase;
|
|
244
|
+
}
|
|
245
|
+
function createTaxInfoHostContext({
|
|
246
|
+
tokenInfo,
|
|
247
|
+
taxInfo,
|
|
248
|
+
vaultInfo,
|
|
249
|
+
feeMode,
|
|
250
|
+
giftVaultFactory,
|
|
251
|
+
hasTaxVaults,
|
|
252
|
+
vaultType,
|
|
253
|
+
copyScope = "tax"
|
|
254
|
+
}) {
|
|
255
|
+
const resolvedFeeMode = feeMode ?? resolveFeeMode(taxInfo, giftVaultFactory);
|
|
256
|
+
const renderSurface = resolveTaxInfoRenderSurface({
|
|
257
|
+
tokenInfo,
|
|
258
|
+
taxInfo,
|
|
259
|
+
hasTaxVaults: hasTaxVaults ?? Boolean(vaultInfo?.found),
|
|
260
|
+
isNonTaxFeeToken: copyScope === "fee"
|
|
261
|
+
});
|
|
262
|
+
const marketPhase = resolveTokenMarketPhase(tokenInfo);
|
|
263
|
+
return {
|
|
264
|
+
tokenInfo: tokenInfo ?? void 0,
|
|
265
|
+
taxInfo: taxInfo ?? null,
|
|
266
|
+
vaultInfo: vaultInfo ?? null,
|
|
267
|
+
feeMode: resolvedFeeMode,
|
|
268
|
+
renderSurface,
|
|
269
|
+
vaultType,
|
|
270
|
+
copyScope,
|
|
271
|
+
isListed: tokenInfo ? tokenInfo.status >= 2 : void 0,
|
|
272
|
+
marketPhase
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
function readTaxVaultHostContext(host) {
|
|
276
|
+
const tokenInfo = host?.tokenInfo;
|
|
277
|
+
const marketPhase = host?.marketPhase ?? resolveTokenMarketPhase(tokenInfo);
|
|
278
|
+
const isListed = host?.isListed ?? Boolean(tokenInfo && tokenInfo.status >= 2);
|
|
279
|
+
const isTaxToken = tokenInfo?.isTaxToken === true;
|
|
280
|
+
return {
|
|
281
|
+
tokenInfo,
|
|
282
|
+
taxInfo: host?.taxInfo ?? null,
|
|
283
|
+
vaultInfo: host?.vaultInfo ?? null,
|
|
284
|
+
feeMode: host?.feeMode ?? "unknown",
|
|
285
|
+
renderSurface: host?.renderSurface ?? "unavailable",
|
|
286
|
+
vaultType: host?.vaultType,
|
|
287
|
+
copyScope: host?.copyScope ?? "tax",
|
|
288
|
+
marketPhase,
|
|
289
|
+
isListed,
|
|
290
|
+
isTaxToken,
|
|
291
|
+
isSupportedCustomVaultToken: isCustomVaultTaxToken(tokenInfo)
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// src/sdk/hostRead.ts
|
|
296
|
+
var portalAbi = [
|
|
297
|
+
{
|
|
298
|
+
name: "getTokenV7",
|
|
299
|
+
type: "function",
|
|
300
|
+
stateMutability: "view",
|
|
301
|
+
inputs: [{ name: "", type: "address" }],
|
|
302
|
+
outputs: [
|
|
303
|
+
{
|
|
304
|
+
type: "tuple",
|
|
305
|
+
components: [
|
|
306
|
+
{ name: "status", type: "uint8" },
|
|
307
|
+
{ name: "reserve", type: "uint256" },
|
|
308
|
+
{ name: "circulatingSupply", type: "uint256" },
|
|
309
|
+
{ name: "price", type: "uint256" },
|
|
310
|
+
{ name: "tokenVersion", type: "uint8" },
|
|
311
|
+
{ name: "r", type: "uint256" },
|
|
312
|
+
{ name: "h", type: "uint256" },
|
|
313
|
+
{ name: "k", type: "uint256" },
|
|
314
|
+
{ name: "dexSupplyThresh", type: "uint256" },
|
|
315
|
+
{ name: "quoteTokenAddress", type: "address" },
|
|
316
|
+
{ name: "nativeToQuoteSwapEnabled", type: "bool" },
|
|
317
|
+
{ name: "extensionID", type: "bytes32" },
|
|
318
|
+
{ name: "taxRate", type: "uint256" },
|
|
319
|
+
{ name: "pool", type: "address" },
|
|
320
|
+
{ name: "progress", type: "uint256" },
|
|
321
|
+
{ name: "lpFeeProfile", type: "uint8" },
|
|
322
|
+
{ name: "dexId", type: "uint8" }
|
|
323
|
+
]
|
|
324
|
+
}
|
|
325
|
+
]
|
|
326
|
+
}
|
|
327
|
+
];
|
|
328
|
+
var taxTokenHelperAbi = [
|
|
329
|
+
{
|
|
330
|
+
name: "getTaxTokenInfo",
|
|
331
|
+
type: "function",
|
|
332
|
+
stateMutability: "view",
|
|
333
|
+
inputs: [{ name: "taxToken", type: "address" }],
|
|
334
|
+
outputs: [
|
|
335
|
+
{
|
|
336
|
+
type: "tuple",
|
|
337
|
+
components: [
|
|
338
|
+
{ name: "marketBps", type: "uint16" },
|
|
339
|
+
{ name: "deflationBps", type: "uint16" },
|
|
340
|
+
{ name: "lpBps", type: "uint16" },
|
|
341
|
+
{ name: "dividendBps", type: "uint16" },
|
|
342
|
+
{ name: "feeRate", type: "uint16" },
|
|
343
|
+
{ name: "burntTokenAmount", type: "uint256" },
|
|
344
|
+
{ name: "totalQuoteSentToDividend", type: "uint256" },
|
|
345
|
+
{ name: "totalQuoteAddedToLiquidity", type: "uint256" },
|
|
346
|
+
{ name: "totalTokenAddedToLiquidity", type: "uint256" },
|
|
347
|
+
{ name: "totalQuoteSentToMarketing", type: "uint256" },
|
|
348
|
+
{ name: "marketingWallet", type: "address" },
|
|
349
|
+
{ name: "quoteToken", type: "address" },
|
|
350
|
+
{ name: "minimumShareBalance", type: "uint256" }
|
|
351
|
+
]
|
|
352
|
+
}
|
|
353
|
+
]
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
name: "getTaxTokenInfoV2",
|
|
357
|
+
type: "function",
|
|
358
|
+
stateMutability: "view",
|
|
359
|
+
inputs: [{ name: "taxToken", type: "address" }],
|
|
360
|
+
outputs: [
|
|
361
|
+
{
|
|
362
|
+
type: "tuple",
|
|
363
|
+
components: [
|
|
364
|
+
{ name: "marketBps", type: "uint16" },
|
|
365
|
+
{ name: "deflationBps", type: "uint16" },
|
|
366
|
+
{ name: "lpBps", type: "uint16" },
|
|
367
|
+
{ name: "dividendBps", type: "uint16" },
|
|
368
|
+
{ name: "buyTaxRate", type: "uint16" },
|
|
369
|
+
{ name: "sellTaxRate", type: "uint16" },
|
|
370
|
+
{ name: "burntTokenAmount", type: "uint256" },
|
|
371
|
+
{ name: "totalQuoteSentToDividend", type: "uint256" },
|
|
372
|
+
{ name: "totalQuoteAddedToLiquidity", type: "uint256" },
|
|
373
|
+
{ name: "totalTokenAddedToLiquidity", type: "uint256" },
|
|
374
|
+
{ name: "totalQuoteSentToMarketing", type: "uint256" },
|
|
375
|
+
{ name: "dividendToken", type: "address" },
|
|
376
|
+
{ name: "quoteToken", type: "address" },
|
|
377
|
+
{ name: "minimumShareBalance", type: "uint256" },
|
|
378
|
+
{
|
|
379
|
+
name: "vaultInfo",
|
|
380
|
+
type: "tuple",
|
|
381
|
+
components: [
|
|
382
|
+
{ name: "addr", type: "address" },
|
|
383
|
+
{ name: "factory", type: "address" },
|
|
384
|
+
{ name: "riskLevel", type: "uint8" },
|
|
385
|
+
{ name: "isOfficialVault", type: "bool" },
|
|
386
|
+
{ name: "isVault", type: "bool" },
|
|
387
|
+
{ name: "isAIConsumer", type: "bool" }
|
|
388
|
+
]
|
|
389
|
+
}
|
|
390
|
+
]
|
|
391
|
+
}
|
|
392
|
+
]
|
|
393
|
+
}
|
|
394
|
+
];
|
|
395
|
+
var vaultPortalAbi = [
|
|
396
|
+
{
|
|
397
|
+
name: "tryGetVault",
|
|
398
|
+
type: "function",
|
|
399
|
+
stateMutability: "view",
|
|
400
|
+
inputs: [{ name: "taxToken", type: "address" }],
|
|
401
|
+
outputs: [
|
|
402
|
+
{ name: "found", type: "bool" },
|
|
403
|
+
{
|
|
404
|
+
name: "info",
|
|
405
|
+
type: "tuple",
|
|
406
|
+
components: [
|
|
407
|
+
{ name: "vault", type: "address" },
|
|
408
|
+
{ name: "vaultFactory", type: "address" },
|
|
409
|
+
{ name: "description", type: "string" },
|
|
410
|
+
{ name: "isOfficial", type: "bool" },
|
|
411
|
+
{ name: "riskLevel", type: "uint8" }
|
|
412
|
+
]
|
|
413
|
+
}
|
|
414
|
+
]
|
|
415
|
+
}
|
|
416
|
+
];
|
|
417
|
+
async function readErc20Symbol(publicClient, address) {
|
|
418
|
+
try {
|
|
419
|
+
const symbol = await publicClient.readContract({
|
|
420
|
+
address,
|
|
421
|
+
abi: erc20Abi,
|
|
422
|
+
functionName: "symbol"
|
|
423
|
+
});
|
|
424
|
+
return typeof symbol === "string" && symbol.trim() ? symbol.trim() : void 0;
|
|
425
|
+
} catch {
|
|
426
|
+
return void 0;
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
async function readErc20Name(publicClient, address) {
|
|
430
|
+
try {
|
|
431
|
+
const name = await publicClient.readContract({
|
|
432
|
+
address,
|
|
433
|
+
abi: erc20Abi,
|
|
434
|
+
functionName: "name"
|
|
435
|
+
});
|
|
436
|
+
return typeof name === "string" && name.trim() ? name.trim() : void 0;
|
|
437
|
+
} catch {
|
|
438
|
+
return void 0;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
async function readErc20Decimals(publicClient, address) {
|
|
442
|
+
try {
|
|
443
|
+
const decimals = await publicClient.readContract({
|
|
444
|
+
address,
|
|
445
|
+
abi: erc20Abi,
|
|
446
|
+
functionName: "decimals"
|
|
447
|
+
});
|
|
448
|
+
return typeof decimals === "number" ? decimals : 18;
|
|
449
|
+
} catch {
|
|
450
|
+
return 18;
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
async function resolvePaymentToken(publicClient, tokenInfo) {
|
|
454
|
+
const quoteTokenAddress = tokenInfo.quoteTokenAddress;
|
|
455
|
+
if (!quoteTokenAddress) return void 0;
|
|
456
|
+
if (quoteTokenAddress === ZERO_ADDRESS) {
|
|
457
|
+
const nativeCurrency = publicClient.chain?.nativeCurrency;
|
|
458
|
+
return {
|
|
459
|
+
address: ZERO_ADDRESS,
|
|
460
|
+
symbol: nativeCurrency?.symbol ?? "NATIVE",
|
|
461
|
+
decimals: nativeCurrency?.decimals ?? 18,
|
|
462
|
+
isNative: true
|
|
463
|
+
};
|
|
464
|
+
}
|
|
465
|
+
if (!isValidAddress(quoteTokenAddress)) return void 0;
|
|
466
|
+
const [symbol, decimals] = await Promise.all([readErc20Symbol(publicClient, quoteTokenAddress), readErc20Decimals(publicClient, quoteTokenAddress)]);
|
|
467
|
+
return {
|
|
468
|
+
address: quoteTokenAddress,
|
|
469
|
+
symbol: symbol ?? "TOKEN",
|
|
470
|
+
decimals,
|
|
471
|
+
isNative: false
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
async function readErc20TokenMetadata(publicClient, tokenAddress) {
|
|
475
|
+
if (!tokenAddress || !isValidAddress(tokenAddress) || tokenAddress === ZERO_ADDRESS) return null;
|
|
476
|
+
const [tokenSymbol, tokenName] = await Promise.all([readErc20Symbol(publicClient, tokenAddress), readErc20Name(publicClient, tokenAddress)]);
|
|
477
|
+
if (!tokenSymbol && !tokenName) return null;
|
|
478
|
+
return {
|
|
479
|
+
tokenSymbol,
|
|
480
|
+
tokenName
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
async function loadTokenRuntimeSnapshot(publicClient, chainId, tokenAddress) {
|
|
484
|
+
if (!tokenAddress || !isValidAddress(tokenAddress) || tokenAddress === ZERO_ADDRESS) return null;
|
|
485
|
+
const metadata = await readErc20TokenMetadata(publicClient, tokenAddress);
|
|
486
|
+
const chainConfig = getTaxVaultHostChainConfig(chainId);
|
|
487
|
+
const baseSnapshot = {
|
|
488
|
+
tokenSymbol: metadata?.tokenSymbol,
|
|
489
|
+
tokenName: metadata?.tokenName,
|
|
490
|
+
copyScope: "tax"
|
|
491
|
+
};
|
|
492
|
+
if (!chainConfig) {
|
|
493
|
+
return {
|
|
494
|
+
...baseSnapshot,
|
|
495
|
+
hasTaxVaults: false,
|
|
496
|
+
hostReadSupported: false,
|
|
497
|
+
hostReadFromChain: false
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
let tokenData;
|
|
501
|
+
try {
|
|
502
|
+
tokenData = await publicClient.readContract({
|
|
503
|
+
address: chainConfig.portal,
|
|
504
|
+
abi: portalAbi,
|
|
505
|
+
functionName: "getTokenV7",
|
|
506
|
+
args: [tokenAddress]
|
|
507
|
+
});
|
|
508
|
+
} catch {
|
|
509
|
+
return {
|
|
510
|
+
...baseSnapshot,
|
|
511
|
+
hasTaxVaults: Boolean(chainConfig.vaultPortal),
|
|
512
|
+
hostReadSupported: true,
|
|
513
|
+
hostReadFromChain: false,
|
|
514
|
+
giftVaultFactory: chainConfig.giftVaultFactory
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
const tokenInfo = parsePortalTokenInfo(tokenData);
|
|
518
|
+
const hasTaxVaults = Boolean(chainConfig.vaultPortal);
|
|
519
|
+
if (!tokenInfo) {
|
|
520
|
+
return {
|
|
521
|
+
...baseSnapshot,
|
|
522
|
+
hasTaxVaults,
|
|
523
|
+
hostReadSupported: true,
|
|
524
|
+
hostReadFromChain: false,
|
|
525
|
+
giftVaultFactory: chainConfig.giftVaultFactory
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
const paymentToken = tokenInfo.exists ? await resolvePaymentToken(publicClient, tokenInfo) : void 0;
|
|
529
|
+
if (!tokenInfo.exists) {
|
|
530
|
+
const host2 = createTaxInfoHostContext({
|
|
531
|
+
tokenInfo,
|
|
532
|
+
giftVaultFactory: chainConfig.giftVaultFactory,
|
|
533
|
+
hasTaxVaults,
|
|
534
|
+
copyScope: "tax"
|
|
535
|
+
});
|
|
536
|
+
return {
|
|
537
|
+
...baseSnapshot,
|
|
538
|
+
tokenInfo,
|
|
539
|
+
host: host2,
|
|
540
|
+
giftVaultFactory: chainConfig.giftVaultFactory,
|
|
541
|
+
paymentToken,
|
|
542
|
+
hasTaxVaults,
|
|
543
|
+
hostReadSupported: true,
|
|
544
|
+
hostReadFromChain: true
|
|
545
|
+
};
|
|
546
|
+
}
|
|
547
|
+
const taxInfoPromise = tokenInfo.isTaxToken && chainConfig.taxTokenHelperAddress ? Promise.allSettled([
|
|
548
|
+
publicClient.readContract({
|
|
549
|
+
address: chainConfig.taxTokenHelperAddress,
|
|
550
|
+
abi: taxTokenHelperAbi,
|
|
551
|
+
functionName: "getTaxTokenInfo",
|
|
552
|
+
args: [tokenAddress]
|
|
553
|
+
}),
|
|
554
|
+
publicClient.readContract({
|
|
555
|
+
address: chainConfig.taxTokenHelperAddress,
|
|
556
|
+
abi: taxTokenHelperAbi,
|
|
557
|
+
functionName: "getTaxTokenInfoV2",
|
|
558
|
+
args: [tokenAddress]
|
|
559
|
+
})
|
|
560
|
+
]) : Promise.resolve(null);
|
|
561
|
+
const vaultInfoPromise = chainConfig.vaultPortal ? publicClient.readContract({
|
|
562
|
+
address: chainConfig.vaultPortal,
|
|
563
|
+
abi: vaultPortalAbi,
|
|
564
|
+
functionName: "tryGetVault",
|
|
565
|
+
args: [tokenAddress]
|
|
566
|
+
}).catch(() => void 0) : Promise.resolve(void 0);
|
|
567
|
+
const [taxResults, vaultData] = await Promise.all([taxInfoPromise, vaultInfoPromise]);
|
|
568
|
+
const baseTaxInfo = Array.isArray(taxResults) && taxResults[0]?.status === "fulfilled" ? taxResults[0].value : void 0;
|
|
569
|
+
const taxInfoV2 = Array.isArray(taxResults) && taxResults[1]?.status === "fulfilled" ? taxResults[1].value : void 0;
|
|
570
|
+
const taxInfo = baseTaxInfo ? parseTaxTokenInfo(baseTaxInfo, taxInfoV2, { wrappedNativeTokenAddress: chainConfig.wrappedNativeTokenAddress }) : void 0;
|
|
571
|
+
const vaultInfo = vaultData ? parseVaultPortalInfo(vaultData) : void 0;
|
|
572
|
+
const host = createTaxInfoHostContext({
|
|
573
|
+
tokenInfo,
|
|
574
|
+
taxInfo,
|
|
575
|
+
vaultInfo,
|
|
576
|
+
giftVaultFactory: chainConfig.giftVaultFactory,
|
|
577
|
+
hasTaxVaults,
|
|
578
|
+
copyScope: "tax"
|
|
579
|
+
});
|
|
580
|
+
return {
|
|
581
|
+
...baseSnapshot,
|
|
582
|
+
tokenInfo,
|
|
583
|
+
taxInfo,
|
|
584
|
+
vaultInfo,
|
|
585
|
+
host,
|
|
586
|
+
giftVaultFactory: chainConfig.giftVaultFactory,
|
|
587
|
+
paymentToken,
|
|
588
|
+
hasTaxVaults,
|
|
589
|
+
hostReadSupported: true,
|
|
590
|
+
hostReadFromChain: true
|
|
591
|
+
};
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
// src/sdk/hostRuntime.ts
|
|
595
|
+
function isResolvedAddress(address) {
|
|
596
|
+
return Boolean(address && isValidAddress(address) && address !== ZERO_ADDRESS);
|
|
597
|
+
}
|
|
598
|
+
function pickAddress(...candidates) {
|
|
599
|
+
for (const candidate of candidates) {
|
|
600
|
+
if (isResolvedAddress(candidate)) return candidate;
|
|
601
|
+
}
|
|
602
|
+
return void 0;
|
|
603
|
+
}
|
|
604
|
+
function resolveAddresses(input, snapshot) {
|
|
605
|
+
return {
|
|
606
|
+
chainId: input.chainId,
|
|
607
|
+
tokenAddress: input.tokenAddress,
|
|
608
|
+
factoryAddressHint: input.factoryAddressHint,
|
|
609
|
+
vaultAddressHint: input.vaultAddressHint,
|
|
610
|
+
factoryAddress: pickAddress(input.factoryAddressHint, snapshot?.vaultInfo?.vaultFactory, snapshot?.taxInfo?.vaultInfo?.factory ?? void 0),
|
|
611
|
+
vaultAddress: pickAddress(input.vaultAddressHint, snapshot?.vaultInfo?.vault, snapshot?.taxInfo?.vaultInfo?.addr ?? void 0)
|
|
612
|
+
};
|
|
613
|
+
}
|
|
614
|
+
function hasPresentationMetadata(result) {
|
|
615
|
+
return Boolean(result.presentation?.tokenName || result.presentation?.tokenSymbol || result.presentation?.tokenImageUrl);
|
|
616
|
+
}
|
|
617
|
+
function resolveTokenMetadataSource(snapshot, presentationDataAvailable) {
|
|
618
|
+
if (presentationDataAvailable) return "host-proxy";
|
|
619
|
+
if (snapshot?.tokenName || snapshot?.tokenSymbol) return "onchain";
|
|
620
|
+
return "unavailable";
|
|
621
|
+
}
|
|
622
|
+
function resolveSources(snapshot, presentationDataAvailable) {
|
|
623
|
+
return {
|
|
624
|
+
tokenMetadata: resolveTokenMetadataSource(snapshot, presentationDataAvailable),
|
|
625
|
+
taxState: snapshot?.taxInfo ? "onchain" : "unavailable",
|
|
626
|
+
vaultState: snapshot?.vaultInfo?.found || snapshot?.taxInfo?.vaultInfo?.isVault ? "onchain" : "unavailable",
|
|
627
|
+
presentation: presentationDataAvailable ? "host-proxy" : "unavailable"
|
|
628
|
+
};
|
|
629
|
+
}
|
|
630
|
+
function collectWarnings(snapshot, addresses) {
|
|
631
|
+
const warnings = [];
|
|
632
|
+
if (!snapshot?.taxInfo) warnings.push("tax-info-unavailable");
|
|
633
|
+
if (snapshot?.tokenInfo?.quoteTokenAddress && !snapshot.paymentToken) warnings.push("payment-token-unavailable");
|
|
634
|
+
if (!addresses.vaultAddress) warnings.push("vault-address-unavailable");
|
|
635
|
+
if (!addresses.factoryAddress) warnings.push("factory-address-unavailable");
|
|
636
|
+
return warnings;
|
|
637
|
+
}
|
|
638
|
+
function resolveChainFailure(snapshot) {
|
|
639
|
+
if (!snapshot) return "chain-read-unavailable";
|
|
640
|
+
if (!snapshot.hostReadSupported) return "unsupported-chain";
|
|
641
|
+
if (!snapshot.hostReadFromChain || !snapshot.tokenInfo) return "chain-read-unavailable";
|
|
642
|
+
if (!snapshot.tokenInfo.exists) return "token-not-found";
|
|
643
|
+
if (!snapshot.tokenInfo.isTaxToken) return "token-not-tax";
|
|
644
|
+
return null;
|
|
645
|
+
}
|
|
646
|
+
function createResult(params) {
|
|
647
|
+
const addresses = resolveAddresses(params.input, params.snapshot);
|
|
648
|
+
const basePresentation = params.presentation ?? null;
|
|
649
|
+
const baseResult = {
|
|
650
|
+
status: params.status,
|
|
651
|
+
policy: params.policy,
|
|
652
|
+
degradeReason: params.degradeReason,
|
|
653
|
+
warnings: collectWarnings(params.snapshot, addresses),
|
|
654
|
+
addresses,
|
|
655
|
+
snapshot: params.snapshot,
|
|
656
|
+
host: params.snapshot?.host ?? void 0,
|
|
657
|
+
paymentToken: params.snapshot?.paymentToken,
|
|
658
|
+
tokenSymbol: basePresentation?.tokenSymbol ?? params.snapshot?.tokenSymbol,
|
|
659
|
+
tokenName: basePresentation?.tokenName ?? params.snapshot?.tokenName,
|
|
660
|
+
tokenImageUrl: basePresentation?.tokenImageUrl,
|
|
661
|
+
tokenDetailHref: basePresentation?.tokenDetailHref,
|
|
662
|
+
chainHref: basePresentation?.chainHref,
|
|
663
|
+
presentation: basePresentation,
|
|
664
|
+
sources: {
|
|
665
|
+
tokenMetadata: "unavailable",
|
|
666
|
+
taxState: "unavailable",
|
|
667
|
+
vaultState: "unavailable",
|
|
668
|
+
presentation: "unavailable"
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
baseResult.sources = resolveSources(params.snapshot, hasPresentationMetadata(baseResult));
|
|
672
|
+
return baseResult;
|
|
673
|
+
}
|
|
674
|
+
function resolveHostRuntimeAddresses(input, snapshot) {
|
|
675
|
+
return resolveAddresses(input, snapshot);
|
|
676
|
+
}
|
|
677
|
+
async function runHostRuntime(input) {
|
|
678
|
+
const policy = input.policy ?? "prefer-full-host";
|
|
679
|
+
if (!isResolvedAddress(input.tokenAddress)) {
|
|
680
|
+
return createResult({
|
|
681
|
+
status: "unavailable",
|
|
682
|
+
input,
|
|
683
|
+
snapshot: null,
|
|
684
|
+
degradeReason: "invalid-token-address",
|
|
685
|
+
policy
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
const snapshot = await loadTokenRuntimeSnapshot(input.publicClient, input.chainId, input.tokenAddress);
|
|
689
|
+
const chainFailure = resolveChainFailure(snapshot);
|
|
690
|
+
if (chainFailure) {
|
|
691
|
+
return createResult({
|
|
692
|
+
status: "unavailable",
|
|
693
|
+
input,
|
|
694
|
+
snapshot,
|
|
695
|
+
degradeReason: chainFailure,
|
|
696
|
+
policy
|
|
697
|
+
});
|
|
698
|
+
}
|
|
699
|
+
let presentation = null;
|
|
700
|
+
let presentationFailure;
|
|
701
|
+
if (input.presentationFetcher) {
|
|
702
|
+
try {
|
|
703
|
+
presentation = await input.presentationFetcher({
|
|
704
|
+
chainId: input.chainId,
|
|
705
|
+
tokenAddress: input.tokenAddress,
|
|
706
|
+
factoryAddress: resolveAddresses(input, snapshot).factoryAddress,
|
|
707
|
+
vaultAddress: resolveAddresses(input, snapshot).vaultAddress,
|
|
708
|
+
snapshot
|
|
709
|
+
});
|
|
710
|
+
if (!presentation) {
|
|
711
|
+
presentationFailure = "host-presentation-unavailable";
|
|
712
|
+
}
|
|
713
|
+
} catch {
|
|
714
|
+
presentationFailure = "host-presentation-unavailable";
|
|
715
|
+
}
|
|
716
|
+
} else {
|
|
717
|
+
presentationFailure = "host-presentation-not-configured";
|
|
718
|
+
}
|
|
719
|
+
if (presentation) {
|
|
720
|
+
return createResult({
|
|
721
|
+
status: "full-host",
|
|
722
|
+
input,
|
|
723
|
+
snapshot,
|
|
724
|
+
presentation,
|
|
725
|
+
policy
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
if (policy === "require-full-host") {
|
|
729
|
+
return createResult({
|
|
730
|
+
status: "unavailable",
|
|
731
|
+
input,
|
|
732
|
+
snapshot,
|
|
733
|
+
degradeReason: presentationFailure === "host-presentation-not-configured" ? "host-presentation-required" : "host-presentation-unavailable",
|
|
734
|
+
policy
|
|
735
|
+
});
|
|
736
|
+
}
|
|
737
|
+
const result = createResult({
|
|
738
|
+
status: "onchain",
|
|
739
|
+
input,
|
|
740
|
+
snapshot,
|
|
741
|
+
degradeReason: presentationFailure,
|
|
742
|
+
policy
|
|
743
|
+
});
|
|
744
|
+
const hostSnapshot = readTaxVaultHostContext(result.host);
|
|
745
|
+
if (!hostSnapshot.isSupportedCustomVaultToken) {
|
|
746
|
+
return {
|
|
747
|
+
...result,
|
|
748
|
+
status: "unavailable",
|
|
749
|
+
degradeReason: "token-not-tax"
|
|
750
|
+
};
|
|
751
|
+
}
|
|
752
|
+
return result;
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// src/sdk/runtimeContext.ts
|
|
756
|
+
var zeroAddress = "0x0000000000000000000000000000000000000000";
|
|
757
|
+
function explorerForChain(chainId) {
|
|
758
|
+
if (chainId === 56) return "https://bscscan.com";
|
|
759
|
+
if (chainId === 97) return "https://testnet.bscscan.com";
|
|
760
|
+
return void 0;
|
|
761
|
+
}
|
|
762
|
+
function chainLabelForChain(chainId) {
|
|
763
|
+
if (chainId === 56) return "BNB Chain";
|
|
764
|
+
if (chainId === 97) return "BNB Testnet";
|
|
765
|
+
return `Chain ${chainId}`;
|
|
766
|
+
}
|
|
767
|
+
function buildRuntimeExtraConfig(input) {
|
|
768
|
+
const hostRuntimeResult = input.hostRuntimeResult;
|
|
769
|
+
const runtimeOverrides = input.runtimeOverrides;
|
|
770
|
+
return {
|
|
771
|
+
...hostRuntimeResult ? {
|
|
772
|
+
hostRuntimeStatus: hostRuntimeResult.status,
|
|
773
|
+
hostRuntimePolicy: hostRuntimeResult.policy,
|
|
774
|
+
hostRuntimeDegradeReason: hostRuntimeResult.degradeReason,
|
|
775
|
+
hostRuntimeWarnings: hostRuntimeResult.warnings
|
|
776
|
+
} : {},
|
|
777
|
+
...hostRuntimeResult?.presentation?.extraConfig ?? {},
|
|
778
|
+
...runtimeOverrides?.extraConfig ?? {}
|
|
779
|
+
};
|
|
780
|
+
}
|
|
781
|
+
function createVaultRuntimeContext(input) {
|
|
782
|
+
const runtimeOverrides = input.runtimeOverrides;
|
|
783
|
+
const resolvedBinding = resolveManifestBinding(input.manifest, {
|
|
784
|
+
chainId: runtimeOverrides?.chainId ?? input.connectedChainId ?? input.hostRuntimeResult?.addresses.chainId,
|
|
785
|
+
factoryAddress: runtimeOverrides?.factoryAddress ?? input.hostRuntimeResult?.addresses.factoryAddress
|
|
786
|
+
});
|
|
787
|
+
const effectiveChainId = runtimeOverrides?.chainId ?? input.hostRuntimeResult?.addresses.chainId ?? input.connectedChainId ?? resolvedBinding?.chainId ?? input.manifest.match.bindings[0]?.chainId ?? 56;
|
|
788
|
+
return {
|
|
789
|
+
chainId: effectiveChainId,
|
|
790
|
+
factoryAddress: runtimeOverrides?.factoryAddress ?? input.hostRuntimeResult?.addresses.factoryAddress ?? resolvedBinding?.factoryAddress ?? zeroAddress,
|
|
791
|
+
tokenAddress: runtimeOverrides?.tokenAddress ?? input.hostRuntimeResult?.addresses.tokenAddress ?? zeroAddress,
|
|
792
|
+
vaultAddress: runtimeOverrides?.vaultAddress ?? input.hostRuntimeResult?.addresses.vaultAddress ?? zeroAddress,
|
|
793
|
+
userAddress: runtimeOverrides?.userAddress,
|
|
794
|
+
tokenSymbol: runtimeOverrides?.tokenSymbol ?? input.hostRuntimeResult?.tokenSymbol,
|
|
795
|
+
tokenName: runtimeOverrides?.tokenName ?? input.hostRuntimeResult?.tokenName,
|
|
796
|
+
tokenImageUrl: runtimeOverrides?.tokenImageUrl ?? input.hostRuntimeResult?.tokenImageUrl,
|
|
797
|
+
explorerBaseUrl: runtimeOverrides?.explorerBaseUrl ?? explorerForChain(effectiveChainId),
|
|
798
|
+
paymentToken: runtimeOverrides?.paymentToken ?? input.hostRuntimeResult?.paymentToken,
|
|
799
|
+
host: runtimeOverrides?.host ?? input.hostRuntimeResult?.host,
|
|
800
|
+
extraConfig: buildRuntimeExtraConfig(input),
|
|
801
|
+
manifest: input.manifest
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// src/sdk/txError.ts
|
|
806
|
+
var defaultMessages = {
|
|
807
|
+
userRejected: "You rejected the wallet request.",
|
|
808
|
+
walletDisconnected: "Connect a wallet before sending this transaction.",
|
|
809
|
+
wrongNetwork: "Switch the wallet to the required chain before sending this transaction.",
|
|
810
|
+
insufficientFunds: "Insufficient wallet balance to complete this transaction.",
|
|
811
|
+
simulationFailed: "The transaction could not pass simulation.",
|
|
812
|
+
reverted: "The contract rejected this transaction.",
|
|
813
|
+
unknown: "Transaction failed. Please check your wallet and try again."
|
|
814
|
+
};
|
|
815
|
+
function isObject(value) {
|
|
816
|
+
return Boolean(value) && typeof value === "object";
|
|
817
|
+
}
|
|
818
|
+
function readString(value) {
|
|
819
|
+
return typeof value === "string" ? value : "";
|
|
820
|
+
}
|
|
821
|
+
function collectMessages(error, depth = 0, seen = /* @__PURE__ */ new Set()) {
|
|
822
|
+
if (depth > 4 || error == null || seen.has(error)) return [];
|
|
823
|
+
seen.add(error);
|
|
824
|
+
if (typeof error === "string") return [error];
|
|
825
|
+
if (!isObject(error)) return [];
|
|
826
|
+
const messages = [
|
|
827
|
+
readString(error.shortMessage),
|
|
828
|
+
readString(error.message),
|
|
829
|
+
readString(error.details),
|
|
830
|
+
readString(error.reason)
|
|
831
|
+
].filter(Boolean);
|
|
832
|
+
return [...messages, ...collectMessages(error.cause, depth + 1, seen)];
|
|
833
|
+
}
|
|
834
|
+
function collectCodes(error, depth = 0, seen = /* @__PURE__ */ new Set()) {
|
|
835
|
+
if (depth > 4 || error == null || seen.has(error)) return [];
|
|
836
|
+
seen.add(error);
|
|
837
|
+
if (!isObject(error)) return [];
|
|
838
|
+
const codes = [error.code, error.name].filter((value) => typeof value === "string" || typeof value === "number");
|
|
839
|
+
return [...codes, ...collectCodes(error.cause, depth + 1, seen)];
|
|
840
|
+
}
|
|
841
|
+
function getTxErrorKind(error) {
|
|
842
|
+
const message = collectMessages(error).join(" ").toLowerCase();
|
|
843
|
+
const codes = collectCodes(error).map((value) => String(value).toLowerCase()).join(" ");
|
|
844
|
+
if (codes.includes("4001") || codes.includes("action_rejected") || codes.includes("userrejectedrequesterror") || /user rejected|user denied|rejected the request|denied transaction|request rejected|cancelled/i.test(message)) {
|
|
845
|
+
return "userRejected";
|
|
846
|
+
}
|
|
847
|
+
if (/wallet is not connected|connector not connected|account not found|no wallet client/i.test(message)) {
|
|
848
|
+
return "walletDisconnected";
|
|
849
|
+
}
|
|
850
|
+
if (/wrong network|switch wallet to|switch network to|required chain/i.test(message)) {
|
|
851
|
+
return "wrongNetwork";
|
|
852
|
+
}
|
|
853
|
+
if (/insufficient funds|exceeds the balance|gas \* price \+ value/i.test(message)) {
|
|
854
|
+
return "insufficientFunds";
|
|
855
|
+
}
|
|
856
|
+
if (/simulation failed|simulatecontract|execution reverted during simulation/i.test(message)) {
|
|
857
|
+
return "simulationFailed";
|
|
858
|
+
}
|
|
859
|
+
if (/execution reverted|reverted with the following reason|contract function .* reverted|call exception/i.test(message)) {
|
|
860
|
+
return "reverted";
|
|
861
|
+
}
|
|
862
|
+
return "unknown";
|
|
863
|
+
}
|
|
864
|
+
function handleTxError(error, messages) {
|
|
865
|
+
const kind = getTxErrorKind(error);
|
|
866
|
+
return messages?.[kind] ?? defaultMessages[kind];
|
|
867
|
+
}
|
|
868
|
+
|
|
869
|
+
export { ZERO_ADDRESS, chainLabelForChain, createTaxInfoHostContext, createVaultRuntimeContext, explorerForChain, formatCountdown, formatPercentBps, formatTokenAmount, getTaxVaultHostChainConfig, getTupleField, getTxErrorKind, handleTxError, isActionAvailableForPhase, isCustomVaultTaxToken, isManifestRuntimeMatch, isSameAddress, isValidAddress, isVaultBindingMatch, loadTokenRuntimeSnapshot, normalizeAddress, parseFeeVaultInfo, parsePortalTokenInfo, parseTaxTokenInfo, parseTokenAmount, parseVaultPortalInfo, readErc20TokenMetadata, readTaxVaultHostContext, resolveFeeMode, resolveHostRuntimeAddresses, resolveManifestBinding, resolveTaxInfoRenderSurface, resolveTokenMarketPhase, resolveVaultBinding, runHostRuntime, shortenAddress, standardErc20Abi };
|
|
870
|
+
//# sourceMappingURL=host.js.map
|
|
871
|
+
//# sourceMappingURL=host.js.map
|