@anywalletkit/protocol-swap2-near-intents 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-HUH3GOAM.js → chunk-GKPYIWQ7.js} +2 -2
- package/dist/{chunk-DA4EDMKN.js → chunk-TCWV5CH4.js} +3 -2
- package/dist/{chunk-DA4EDMKN.js.map → chunk-TCWV5CH4.js.map} +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/protocol.cjs +2 -1
- package/dist/protocol.cjs.map +1 -1
- package/dist/protocol.d.cts +1 -1
- package/dist/protocol.d.ts +1 -1
- package/dist/protocol.js +2 -2
- package/dist/provider.cjs +2 -1
- package/dist/provider.cjs.map +1 -1
- package/dist/provider.js +1 -1
- package/package.json +17 -9
- /package/dist/{chunk-HUH3GOAM.js.map → chunk-GKPYIWQ7.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
nearIntentsProvider
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-TCWV5CH4.js";
|
|
4
4
|
import {
|
|
5
5
|
nearIntents
|
|
6
6
|
} from "./chunk-JBVOUD6Q.js";
|
|
@@ -24,4 +24,4 @@ var NearIntentsSwap2Protocol = class extends SingleProviderSwap2 {
|
|
|
24
24
|
export {
|
|
25
25
|
NearIntentsSwap2Protocol
|
|
26
26
|
};
|
|
27
|
-
//# sourceMappingURL=chunk-
|
|
27
|
+
//# sourceMappingURL=chunk-GKPYIWQ7.js.map
|
|
@@ -226,6 +226,7 @@ function nearIntentsProvider(config = {}) {
|
|
|
226
226
|
const s = await res.json();
|
|
227
227
|
const map = {
|
|
228
228
|
PENDING_DEPOSIT: "pending",
|
|
229
|
+
KNOWN_DEPOSIT_TX: "pending",
|
|
229
230
|
INCOMPLETE_DEPOSIT: "pending",
|
|
230
231
|
PROCESSING: "pending",
|
|
231
232
|
SUCCESS: "completed",
|
|
@@ -233,7 +234,7 @@ function nearIntentsProvider(config = {}) {
|
|
|
233
234
|
REFUNDED: "refunded"
|
|
234
235
|
};
|
|
235
236
|
const state = map[s.status ?? "PENDING_DEPOSIT"] ?? "pending";
|
|
236
|
-
const depositReceived = s.status === "PROCESSING" || s.status === "INCOMPLETE_DEPOSIT";
|
|
237
|
+
const depositReceived = s.status === "KNOWN_DEPOSIT_TX" || s.status === "PROCESSING" || s.status === "INCOMPLETE_DEPOSIT";
|
|
237
238
|
const destTx = txHashOf(s.swapDetails?.destinationChainTxHashes?.[0]);
|
|
238
239
|
return { state, depositReceived, ...destTx ? { destTxHash: destTx } : {} };
|
|
239
240
|
} catch {
|
|
@@ -246,4 +247,4 @@ function nearIntentsProvider(config = {}) {
|
|
|
246
247
|
export {
|
|
247
248
|
nearIntentsProvider
|
|
248
249
|
};
|
|
249
|
-
//# sourceMappingURL=chunk-
|
|
250
|
+
//# sourceMappingURL=chunk-TCWV5CH4.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.ts"],"sourcesContent":["import {nearIntents as cfg, nearIntentsChainRefusal, type NearIntentsSuspendedChains} from \"./config.js\";\nimport {describeNearIntentsActivity} from \"./activity.js\";\nimport {timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {CC_DEST, ccAsset, ccAssetByToken, ccChain} from \"@anywalletkit/swap2-assets\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * NEAR Intents (1Click) provider — the core route, broadest coverage. Ported\n * from a production 1Click integration:\n * dry quote → pricing preview; live quote → depositAddress the user funds\n * from any wallet; status polled by depositAddress.\n * Runs server-side, so the partner JWT stays here (no proxy needed). Defensive:\n * any API error yields a null quote so the provider drops out of that round.\n */\n\nconst ONE_CLICK_DEFAULT = \"https://1click.chaindefuser.com/v0\";\nconst QUOTE_TTL_MS = 55_000;\n\n/** intentId durably carries both status lookup keys (memo is quote-specific). */\nconst INTENT_PREFIX = \"near1click:\";\n\nfunction encodeIntent(depositAddress: string, depositMemo: string | null): string {\n return `${INTENT_PREFIX}${encodeURIComponent(depositAddress)}|${encodeURIComponent(depositMemo ?? \"\")}`;\n}\n\nfunction decodeIntent(intentId: string): {depositAddress: string; depositMemo?: string} {\n try {\n if (!intentId.startsWith(INTENT_PREFIX)) throw new Error(\"unsupported id version\");\n const raw = intentId.slice(INTENT_PREFIX.length);\n const parts = raw.split(\"|\");\n if (parts.length !== 2 || !parts[0]) throw new Error(\"invalid id shape\");\n const depositAddress = decodeURIComponent(parts[0]);\n const memo = decodeURIComponent(parts[1] ?? \"\");\n if (!depositAddress) throw new Error(\"empty deposit address\");\n return {depositAddress, ...(memo ? {depositMemo: memo} : {})};\n } catch {\n throw new Error(\"near-intents: malformed intent id\");\n }\n}\n\nfunction authHeaders(jwtOverride?: string): Record<string, string> {\n const h: Record<string, string> = {\"content-type\": \"application/json\", accept: \"application/json\"};\n const jwt = jwtOverride;\n if (jwt) h.authorization = `Bearer ${jwt}`;\n return h;\n}\n\n/** Our integrator fee, injected server-side when a recipient is configured. */\nfunction appFees(recipient?: string, bps?: number): {recipient: string; fee: number}[] | undefined {\n return recipient !== undefined && bps !== undefined ? [{recipient, fee: bps}] : undefined;\n}\n\n/**\n * Per-source deposit + refund config. Every live default keeps failed-swap\n * ownership on the caller's source-chain address.\n */\nfunction depositConfig(_sourceChain: string, refundAddress: string, _dry: boolean) {\n // Every source refunds to the caller's own source-chain address (Zcash\n // included — a t-address placeholder serves dry quotes since 2026-10-18).\n // Never redirect failed swaps to an integrator-owned NEAR account.\n return {depositType: \"ORIGIN_CHAIN\", refundType: \"ORIGIN_CHAIN\", refundTo: refundAddress};\n}\n\n/** Placeholder sender/recipient for dry quotes (1Click requires the fields). */\nconst PLACEHOLDER: Record<string, string> = {\n bitcoin: \"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq\",\n ton: \"UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ\",\n // NOT a token mint: with the USDC mint here, every dry quote whose ORIGIN\n // was Solana USDC answered 500 \"Internal server error\" (2026-10-09) — a\n // refund \"to the asset's own mint\" trips 1Click. The incinerator is a\n // plain, valid system address.\n solana: \"1nc1nerator11111111111111111111111111111111\",\n tron: \"TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9\",\n // NEAR refunds go to an account id; the registrar account always exists.\n near: \"near\",\n // A live transparent address (exchange hot wallet); dry quotes only.\n zcash: \"t1KfwsnwJeNRVjQGBDZhwKskpQbih2qx5Ua\",\n eip155: \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",\n};\n\nfunction placeholderFor(chain: string): string {\n return PLACEHOLDER[chain.split(\":\")[0] ?? \"\"] ?? PLACEHOLDER.eip155!;\n}\n\nfunction deadlineIn(minutes: number): string {\n return new Date(Date.now() + minutes * 60_000).toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n}\n\n/**\n * dest asset id for ANY chain in the catalog (inbound → Ethereum, or the step-2\n * off-ramp → any supported chain). Falls back to the Ethereum omft pattern for\n * a mainnet ERC-20 that isn't in the curated catalog.\n */\nfunction destAssetId(destChain: string, destToken: string): string | null {\n const asset = ccAssetByToken(destChain, destToken);\n if (asset) return asset.assetId;\n if (destChain === CC_DEST.caip2 && /^0x[0-9a-fA-F]{40}$/.test(destToken)) {\n return `nep141:eth-${destToken.toLowerCase()}.omft.near`;\n }\n return null;\n}\n\ntype OneClickQuote = {\n quote?: Record<string, unknown>;\n correlationId?: string;\n error?: string;\n message?: string;\n};\n\n/** 1Click returns tx hashes either as strings or {hash, explorerUrl}. */\nfunction txHashOf(entry: unknown): string | null {\n if (!entry) return null;\n if (typeof entry === \"string\") return entry;\n const h = (entry as {hash?: string}).hash;\n return typeof h === \"string\" ? h : null;\n}\n\n/** Explicit constructor configuration; no deployment environment is read. */\nexport interface NearIntentsProviderConfig {\n enabled?: boolean;\n apiUrl?: string;\n jwt?: string;\n feeRecipient?: string;\n feeBps?: number;\n /** Corridors the app has paused (caip2 → reason): refused up front, by name, until the app lifts them. */\n suspendedChains?: NearIntentsSuspendedChains;\n}\n\nexport function nearIntentsProvider(config: NearIntentsProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const parsedApiUrl = new URL(config.apiUrl ?? ONE_CLICK_DEFAULT);\n if (parsedApiUrl.protocol !== \"https:\" && parsedApiUrl.protocol !== \"http:\") {\n throw new Error(\"near-intents: apiUrl must use http or https\");\n }\n const apiBase = parsedApiUrl.toString().replace(/\\/$/, \"\");\n const hasRecipient = config.feeRecipient !== undefined;\n const hasBps = config.feeBps !== undefined;\n if (hasRecipient !== hasBps) throw new Error(\"near-intents: feeRecipient and feeBps must be configured together\");\n if (hasRecipient && (!config.feeRecipient!.trim() || !Number.isInteger(config.feeBps) || config.feeBps! <= 0 || config.feeBps! > 10_000)) {\n throw new Error(\"near-intents: fee config requires a recipient and feeBps between 1 and 10000\");\n }\n return {\n name: \"near_intents\",\n describeActivity: describeNearIntentsActivity,\n enabled: () => config.enabled ?? true,\n\n // Capability discovery comes from the provider itself, so it can run alone\n // or inside the optional aggregator without a central capability table.\n supportsChain: (chain: string) => cfg.supportsChain(chain),\n supportsChainPair: (fromChain: string, toChain: string) => cfg.supports(fromChain, toChain),\n supportsRoute(from: Asset, to: Asset): boolean {\n // Chain-level gate first (namespace, catalog listing, hand-suspended\n // corridors such as TON while the HOT bridge is dark) …\n if (!cfg.supports(from.chain, to.chain)) return false;\n // … then only pairs present in the curated catalog are offered — and only\n // those with a 1Click asset id (LI.FI-only tokens carry an empty assetId).\n // Both ends: a destination 1Click doesn't list (Unichain, MegaETH, …)\n // answered \"unknown asset\" on every quote (589 of the 2026-10-10 matrix).\n const asset = ccAsset(from.chain, from.token);\n return !!ccChain(from.chain) && !!asset?.assetId && !!destAssetId(to.chain, to.token);\n },\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n // Every refusal below names itself: on the server these lines are the\n // only visibility into WHY a live quote returned null (the wire answer\n // is just `null`), and \"no route\" bugs hide in exactly that silence.\n const refuse = (reason: string): null => {\n const detail = `${reason} [dry=${params.dry !== false} ${params.sourceChain}->${params.destChain} amount=${params.amountIn}]`;\n // Caller fields and 1Click text are untrusted: no control characters in server logs.\n console.warn(`near-intents: no quote — ${detail.replace(/[\\u0000-\\u001f\\u007f]/g, \" \")}`);\n params.onRefusal?.(detail);\n return null;\n };\n // Up-front, named refusals — no wire call for a corridor 1Click cannot\n // serve: a chain outside its list / suspended by hand, or a token the\n // catalog carries without a 1Click asset id (\"1Click does not list …\").\n const paused = config.suspendedChains ?? {};\n const chainRefusal = nearIntentsChainRefusal(params.sourceChain, paused) ?? nearIntentsChainRefusal(params.destChain, paused);\n if (chainRefusal) return refuse(chainRefusal);\n const origin = ccAsset(params.sourceChain, params.sourceToken);\n if (!origin?.assetId) return refuse(`1Click does not list ${params.sourceChain} ${params.sourceToken}`);\n const destination = destAssetId(params.destChain, params.destToken);\n if (!destination) return refuse(`1Click does not list ${params.destChain} ${params.destToken}`);\n const dry = params.dry !== false;\n // A live quote derives the deposit address from the refund config —\n // never create one without a real refund destination.\n const refund = params.refundAddress ?? (dry ? placeholderFor(params.sourceChain) : \"\");\n const dcfg = depositConfig(params.sourceChain, refund, dry);\n if (!dry && !dcfg.refundTo) return refuse(\"live quote without a refund address\");\n\n const requestedDeadline = deadlineIn(60);\n const body: Record<string, unknown> = {\n dry,\n // FLEX_INPUT (exchange flow): the address accepts any amount; amountIn\n // is just the pricing notional. Verified against the live API.\n swapType: params.flex ? \"FLEX_INPUT\" : \"EXACT_INPUT\",\n slippageTolerance: params.slippageBps ?? 100,\n originAsset: origin.assetId,\n depositType: dcfg.depositType,\n destinationAsset: destination,\n amount: params.amountIn,\n refundTo: dcfg.refundTo,\n refundType: dcfg.refundType,\n recipient: params.destAddress,\n recipientType: \"DESTINATION_CHAIN\",\n deadline: requestedDeadline,\n };\n const fees = appFees(config.feeRecipient, config.feeBps);\n if (fees) body.appFees = fees;\n\n try {\n // 1Click's solver auction flaps: the same body can answer 400 \"No\n // liquidity available\" and 201 seconds apart (observed live on\n // TON USDT -> ETH). A transient flap on the EXECUTION quote would\n // surface as a terminal \"no route\" right after a successful display\n // quote, so ride through it: up to two retries on liquidity flaps,\n // 5xx and network errors. Real rejections (bad address, unknown\n // asset) still fail on the first answer.\n let res: Response | null = null;\n let data: OneClickQuote = {};\n for (let attempt = 0; ; attempt++) {\n try {\n res = await fetch(`${apiBase}/quote`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify(body),\n signal: signal ?? timeoutSignal(12_000),\n });\n data = (await res.json().catch(() => ({}))) as OneClickQuote;\n } catch (err) {\n if (attempt >= 2 || signal?.aborted) throw err;\n res = null;\n }\n if (res?.ok) break;\n const flaky =\n res === null ||\n res.status >= 500 ||\n (res.status === 400 && /no liquidity/i.test(String(data.message ?? \"\")));\n if (!flaky || attempt >= 2 || signal?.aborted) break;\n await new Promise((resolve) => setTimeout(resolve, 500 * (attempt + 1)));\n }\n if (!res?.ok) return refuse(`1Click ${res?.status ?? \"network error\"}: ${String(data.message ?? \"\").slice(0, 200)}`);\n const q = (data.quote ?? {}) as Record<string, unknown>;\n\n const depositAddress = typeof q.depositAddress === \"string\" ? q.depositAddress : \"\";\n if (!dry && !depositAddress) return refuse(\"live quote came back without a deposit address\");\n const inUsd = Number.parseFloat(String(q.amountInUsd ?? \"0\"));\n const outUsd = Number.parseFloat(String(q.amountOutUsd ?? \"0\"));\n const parsedDeadline = Date.parse(String(q.deadline ?? \"\"));\n if (!dry && (!Number.isFinite(parsedDeadline) || parsedDeadline <= Date.now())) return refuse(`unusable deadline ${String(q.deadline)}`);\n const deadline = Number.isFinite(parsedDeadline) && parsedDeadline > Date.now()\n ? Math.min(parsedDeadline, Date.now() + QUOTE_TTL_MS)\n : Date.now() + QUOTE_TTL_MS;\n\n if (q.amountIn !== undefined && String(q.amountIn) !== params.amountIn) return refuse(`amountIn mismatch (${String(q.amountIn)} vs ${params.amountIn})`);\n\n // amountOut is optimistic, not a guaranteed floor. Live execution must\n // not fabricate a minimum when the provider omits it.\n if (q.minAmountOut === undefined || q.minAmountOut === null) return refuse(\"quote has no minAmountOut\");\n const minDestAmount = String(q.minAmountOut);\n if (params.minAmountOut !== undefined && BigInt(minDestAmount) < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${minDestAmount} < floor=${params.minAmountOut})`);\n const depositMemo =\n (typeof q.depositMemo === \"string\" && q.depositMemo) ||\n (typeof q.memo === \"string\" && q.memo) ||\n null;\n return {\n provider: \"near_intents\",\n intentId: depositAddress ? encodeIntent(depositAddress, depositMemo) : `dry:${crypto.randomUUID()}`,\n depositAddress,\n depositMemo,\n sourceAmount: params.amountIn,\n destAmount: String(q.amountOut ?? \"0\"),\n minDestAmount,\n feeUsd: Math.max(0, inUsd - outUsd),\n etaSeconds: Number(q.timeEstimate ?? 60),\n reliability: 0.95,\n validUntilMs: deadline,\n };\n } catch (err) {\n return refuse(`threw: ${err instanceof Error ? err.message.slice(0, 200) : String(err).slice(0, 200)}`);\n }\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n return {\n chain: \"\",\n to: quote.depositAddress,\n value: quote.sourceAmount,\n ...(quote.depositMemo ? {memo: quote.depositMemo} : {}),\n };\n },\n\n async notifyDeposit(intentId: string, txHash: string): Promise<void> {\n const {depositAddress} = decodeIntent(intentId);\n const res = await fetch(`${apiBase}/deposit/submit`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify({depositAddress, txHash}),\n signal: timeoutSignal(12_000),\n });\n if (!res.ok) throw new Error(`near-intents: deposit notification failed (${res.status})`);\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n const {depositAddress, depositMemo} = decodeIntent(ref.intentId);\n // Durable retry: BaseSwap2Protocol embeds the source hash in the swap2\n // id. If the post-broadcast notify failed, every status poll retries it.\n if (ref.sourceTxHash) {\n await this.notifyDeposit?.(ref.intentId, ref.sourceTxHash).catch(() => {});\n }\n try {\n const query = new URLSearchParams({depositAddress});\n if (depositMemo) query.set(\"depositMemo\", depositMemo);\n const res = await fetch(\n `${apiBase}/status?${query.toString()}`,\n {headers: authHeaders(config.jwt), signal: timeoutSignal(12_000)},\n );\n if (!res.ok) return {state: \"pending\"};\n const s = (await res.json()) as {\n status?: string;\n swapDetails?: {destinationChainTxHashes?: unknown[]};\n };\n const map: Record<string, IntentStatus[\"state\"]> = {\n PENDING_DEPOSIT: \"pending\",\n INCOMPLETE_DEPOSIT: \"pending\",\n PROCESSING: \"pending\",\n SUCCESS: \"completed\",\n FAILED: \"failed\",\n REFUNDED: \"refunded\",\n };\n const state = map[s.status ?? \"PENDING_DEPOSIT\"] ?? \"pending\";\n const depositReceived = s.status === \"PROCESSING\" || s.status === \"INCOMPLETE_DEPOSIT\";\n const destTx = txHashOf(s.swapDetails?.destinationChainTxHashes?.[0]);\n return {state, depositReceived, ...(destTx ? {destTxHash: destTx} : {})};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.ts"],"sourcesContent":["import {nearIntents as cfg, nearIntentsChainRefusal, type NearIntentsSuspendedChains} from \"./config.js\";\nimport {describeNearIntentsActivity} from \"./activity.js\";\nimport {timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {CC_DEST, ccAsset, ccAssetByToken, ccChain} from \"@anywalletkit/swap2-assets\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * NEAR Intents (1Click) provider — the core route, broadest coverage. Ported\n * from a production 1Click integration:\n * dry quote → pricing preview; live quote → depositAddress the user funds\n * from any wallet; status polled by depositAddress.\n * Runs server-side, so the partner JWT stays here (no proxy needed). Defensive:\n * any API error yields a null quote so the provider drops out of that round.\n */\n\nconst ONE_CLICK_DEFAULT = \"https://1click.chaindefuser.com/v0\";\nconst QUOTE_TTL_MS = 55_000;\n\n/** intentId durably carries both status lookup keys (memo is quote-specific). */\nconst INTENT_PREFIX = \"near1click:\";\n\nfunction encodeIntent(depositAddress: string, depositMemo: string | null): string {\n return `${INTENT_PREFIX}${encodeURIComponent(depositAddress)}|${encodeURIComponent(depositMemo ?? \"\")}`;\n}\n\nfunction decodeIntent(intentId: string): {depositAddress: string; depositMemo?: string} {\n try {\n if (!intentId.startsWith(INTENT_PREFIX)) throw new Error(\"unsupported id version\");\n const raw = intentId.slice(INTENT_PREFIX.length);\n const parts = raw.split(\"|\");\n if (parts.length !== 2 || !parts[0]) throw new Error(\"invalid id shape\");\n const depositAddress = decodeURIComponent(parts[0]);\n const memo = decodeURIComponent(parts[1] ?? \"\");\n if (!depositAddress) throw new Error(\"empty deposit address\");\n return {depositAddress, ...(memo ? {depositMemo: memo} : {})};\n } catch {\n throw new Error(\"near-intents: malformed intent id\");\n }\n}\n\nfunction authHeaders(jwtOverride?: string): Record<string, string> {\n const h: Record<string, string> = {\"content-type\": \"application/json\", accept: \"application/json\"};\n const jwt = jwtOverride;\n if (jwt) h.authorization = `Bearer ${jwt}`;\n return h;\n}\n\n/** Our integrator fee, injected server-side when a recipient is configured. */\nfunction appFees(recipient?: string, bps?: number): {recipient: string; fee: number}[] | undefined {\n return recipient !== undefined && bps !== undefined ? [{recipient, fee: bps}] : undefined;\n}\n\n/**\n * Per-source deposit + refund config. Every live default keeps failed-swap\n * ownership on the caller's source-chain address.\n */\nfunction depositConfig(_sourceChain: string, refundAddress: string, _dry: boolean) {\n // Every source refunds to the caller's own source-chain address (Zcash\n // included — a t-address placeholder serves dry quotes since 2026-10-18).\n // Never redirect failed swaps to an integrator-owned NEAR account.\n return {depositType: \"ORIGIN_CHAIN\", refundType: \"ORIGIN_CHAIN\", refundTo: refundAddress};\n}\n\n/** Placeholder sender/recipient for dry quotes (1Click requires the fields). */\nconst PLACEHOLDER: Record<string, string> = {\n bitcoin: \"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq\",\n ton: \"UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ\",\n // NOT a token mint: with the USDC mint here, every dry quote whose ORIGIN\n // was Solana USDC answered 500 \"Internal server error\" (2026-10-09) — a\n // refund \"to the asset's own mint\" trips 1Click. The incinerator is a\n // plain, valid system address.\n solana: \"1nc1nerator11111111111111111111111111111111\",\n tron: \"TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9\",\n // NEAR refunds go to an account id; the registrar account always exists.\n near: \"near\",\n // A live transparent address (exchange hot wallet); dry quotes only.\n zcash: \"t1KfwsnwJeNRVjQGBDZhwKskpQbih2qx5Ua\",\n eip155: \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",\n};\n\nfunction placeholderFor(chain: string): string {\n return PLACEHOLDER[chain.split(\":\")[0] ?? \"\"] ?? PLACEHOLDER.eip155!;\n}\n\nfunction deadlineIn(minutes: number): string {\n return new Date(Date.now() + minutes * 60_000).toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n}\n\n/**\n * dest asset id for ANY chain in the catalog (inbound → Ethereum, or the step-2\n * off-ramp → any supported chain). Falls back to the Ethereum omft pattern for\n * a mainnet ERC-20 that isn't in the curated catalog.\n */\nfunction destAssetId(destChain: string, destToken: string): string | null {\n const asset = ccAssetByToken(destChain, destToken);\n if (asset) return asset.assetId;\n if (destChain === CC_DEST.caip2 && /^0x[0-9a-fA-F]{40}$/.test(destToken)) {\n return `nep141:eth-${destToken.toLowerCase()}.omft.near`;\n }\n return null;\n}\n\ntype OneClickQuote = {\n quote?: Record<string, unknown>;\n correlationId?: string;\n error?: string;\n message?: string;\n};\n\n/** 1Click returns tx hashes either as strings or {hash, explorerUrl}. */\nfunction txHashOf(entry: unknown): string | null {\n if (!entry) return null;\n if (typeof entry === \"string\") return entry;\n const h = (entry as {hash?: string}).hash;\n return typeof h === \"string\" ? h : null;\n}\n\n/** Explicit constructor configuration; no deployment environment is read. */\nexport interface NearIntentsProviderConfig {\n enabled?: boolean;\n apiUrl?: string;\n jwt?: string;\n feeRecipient?: string;\n feeBps?: number;\n /** Corridors the app has paused (caip2 → reason): refused up front, by name, until the app lifts them. */\n suspendedChains?: NearIntentsSuspendedChains;\n}\n\nexport function nearIntentsProvider(config: NearIntentsProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const parsedApiUrl = new URL(config.apiUrl ?? ONE_CLICK_DEFAULT);\n if (parsedApiUrl.protocol !== \"https:\" && parsedApiUrl.protocol !== \"http:\") {\n throw new Error(\"near-intents: apiUrl must use http or https\");\n }\n const apiBase = parsedApiUrl.toString().replace(/\\/$/, \"\");\n const hasRecipient = config.feeRecipient !== undefined;\n const hasBps = config.feeBps !== undefined;\n if (hasRecipient !== hasBps) throw new Error(\"near-intents: feeRecipient and feeBps must be configured together\");\n if (hasRecipient && (!config.feeRecipient!.trim() || !Number.isInteger(config.feeBps) || config.feeBps! <= 0 || config.feeBps! > 10_000)) {\n throw new Error(\"near-intents: fee config requires a recipient and feeBps between 1 and 10000\");\n }\n return {\n name: \"near_intents\",\n describeActivity: describeNearIntentsActivity,\n enabled: () => config.enabled ?? true,\n\n // Capability discovery comes from the provider itself, so it can run alone\n // or inside the optional aggregator without a central capability table.\n supportsChain: (chain: string) => cfg.supportsChain(chain),\n supportsChainPair: (fromChain: string, toChain: string) => cfg.supports(fromChain, toChain),\n supportsRoute(from: Asset, to: Asset): boolean {\n // Chain-level gate first (namespace, catalog listing, hand-suspended\n // corridors such as TON while the HOT bridge is dark) …\n if (!cfg.supports(from.chain, to.chain)) return false;\n // … then only pairs present in the curated catalog are offered — and only\n // those with a 1Click asset id (LI.FI-only tokens carry an empty assetId).\n // Both ends: a destination 1Click doesn't list (Unichain, MegaETH, …)\n // answered \"unknown asset\" on every quote (589 of the 2026-10-10 matrix).\n const asset = ccAsset(from.chain, from.token);\n return !!ccChain(from.chain) && !!asset?.assetId && !!destAssetId(to.chain, to.token);\n },\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n // Every refusal below names itself: on the server these lines are the\n // only visibility into WHY a live quote returned null (the wire answer\n // is just `null`), and \"no route\" bugs hide in exactly that silence.\n const refuse = (reason: string): null => {\n const detail = `${reason} [dry=${params.dry !== false} ${params.sourceChain}->${params.destChain} amount=${params.amountIn}]`;\n // Caller fields and 1Click text are untrusted: no control characters in server logs.\n console.warn(`near-intents: no quote — ${detail.replace(/[\\u0000-\\u001f\\u007f]/g, \" \")}`);\n params.onRefusal?.(detail);\n return null;\n };\n // Up-front, named refusals — no wire call for a corridor 1Click cannot\n // serve: a chain outside its list / suspended by hand, or a token the\n // catalog carries without a 1Click asset id (\"1Click does not list …\").\n const paused = config.suspendedChains ?? {};\n const chainRefusal = nearIntentsChainRefusal(params.sourceChain, paused) ?? nearIntentsChainRefusal(params.destChain, paused);\n if (chainRefusal) return refuse(chainRefusal);\n const origin = ccAsset(params.sourceChain, params.sourceToken);\n if (!origin?.assetId) return refuse(`1Click does not list ${params.sourceChain} ${params.sourceToken}`);\n const destination = destAssetId(params.destChain, params.destToken);\n if (!destination) return refuse(`1Click does not list ${params.destChain} ${params.destToken}`);\n const dry = params.dry !== false;\n // A live quote derives the deposit address from the refund config —\n // never create one without a real refund destination.\n const refund = params.refundAddress ?? (dry ? placeholderFor(params.sourceChain) : \"\");\n const dcfg = depositConfig(params.sourceChain, refund, dry);\n if (!dry && !dcfg.refundTo) return refuse(\"live quote without a refund address\");\n\n const requestedDeadline = deadlineIn(60);\n const body: Record<string, unknown> = {\n dry,\n // FLEX_INPUT (exchange flow): the address accepts any amount; amountIn\n // is just the pricing notional. Verified against the live API.\n swapType: params.flex ? \"FLEX_INPUT\" : \"EXACT_INPUT\",\n slippageTolerance: params.slippageBps ?? 100,\n originAsset: origin.assetId,\n depositType: dcfg.depositType,\n destinationAsset: destination,\n amount: params.amountIn,\n refundTo: dcfg.refundTo,\n refundType: dcfg.refundType,\n recipient: params.destAddress,\n recipientType: \"DESTINATION_CHAIN\",\n deadline: requestedDeadline,\n };\n const fees = appFees(config.feeRecipient, config.feeBps);\n if (fees) body.appFees = fees;\n\n try {\n // 1Click's solver auction flaps: the same body can answer 400 \"No\n // liquidity available\" and 201 seconds apart (observed live on\n // TON USDT -> ETH). A transient flap on the EXECUTION quote would\n // surface as a terminal \"no route\" right after a successful display\n // quote, so ride through it: up to two retries on liquidity flaps,\n // 5xx and network errors. Real rejections (bad address, unknown\n // asset) still fail on the first answer.\n let res: Response | null = null;\n let data: OneClickQuote = {};\n for (let attempt = 0; ; attempt++) {\n try {\n res = await fetch(`${apiBase}/quote`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify(body),\n signal: signal ?? timeoutSignal(12_000),\n });\n data = (await res.json().catch(() => ({}))) as OneClickQuote;\n } catch (err) {\n if (attempt >= 2 || signal?.aborted) throw err;\n res = null;\n }\n if (res?.ok) break;\n const flaky =\n res === null ||\n res.status >= 500 ||\n (res.status === 400 && /no liquidity/i.test(String(data.message ?? \"\")));\n if (!flaky || attempt >= 2 || signal?.aborted) break;\n await new Promise((resolve) => setTimeout(resolve, 500 * (attempt + 1)));\n }\n if (!res?.ok) return refuse(`1Click ${res?.status ?? \"network error\"}: ${String(data.message ?? \"\").slice(0, 200)}`);\n const q = (data.quote ?? {}) as Record<string, unknown>;\n\n const depositAddress = typeof q.depositAddress === \"string\" ? q.depositAddress : \"\";\n if (!dry && !depositAddress) return refuse(\"live quote came back without a deposit address\");\n const inUsd = Number.parseFloat(String(q.amountInUsd ?? \"0\"));\n const outUsd = Number.parseFloat(String(q.amountOutUsd ?? \"0\"));\n const parsedDeadline = Date.parse(String(q.deadline ?? \"\"));\n if (!dry && (!Number.isFinite(parsedDeadline) || parsedDeadline <= Date.now())) return refuse(`unusable deadline ${String(q.deadline)}`);\n const deadline = Number.isFinite(parsedDeadline) && parsedDeadline > Date.now()\n ? Math.min(parsedDeadline, Date.now() + QUOTE_TTL_MS)\n : Date.now() + QUOTE_TTL_MS;\n\n if (q.amountIn !== undefined && String(q.amountIn) !== params.amountIn) return refuse(`amountIn mismatch (${String(q.amountIn)} vs ${params.amountIn})`);\n\n // amountOut is optimistic, not a guaranteed floor. Live execution must\n // not fabricate a minimum when the provider omits it.\n if (q.minAmountOut === undefined || q.minAmountOut === null) return refuse(\"quote has no minAmountOut\");\n const minDestAmount = String(q.minAmountOut);\n if (params.minAmountOut !== undefined && BigInt(minDestAmount) < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${minDestAmount} < floor=${params.minAmountOut})`);\n const depositMemo =\n (typeof q.depositMemo === \"string\" && q.depositMemo) ||\n (typeof q.memo === \"string\" && q.memo) ||\n null;\n return {\n provider: \"near_intents\",\n intentId: depositAddress ? encodeIntent(depositAddress, depositMemo) : `dry:${crypto.randomUUID()}`,\n depositAddress,\n depositMemo,\n sourceAmount: params.amountIn,\n destAmount: String(q.amountOut ?? \"0\"),\n minDestAmount,\n feeUsd: Math.max(0, inUsd - outUsd),\n etaSeconds: Number(q.timeEstimate ?? 60),\n reliability: 0.95,\n validUntilMs: deadline,\n };\n } catch (err) {\n return refuse(`threw: ${err instanceof Error ? err.message.slice(0, 200) : String(err).slice(0, 200)}`);\n }\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n return {\n chain: \"\",\n to: quote.depositAddress,\n value: quote.sourceAmount,\n ...(quote.depositMemo ? {memo: quote.depositMemo} : {}),\n };\n },\n\n async notifyDeposit(intentId: string, txHash: string): Promise<void> {\n const {depositAddress} = decodeIntent(intentId);\n const res = await fetch(`${apiBase}/deposit/submit`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify({depositAddress, txHash}),\n signal: timeoutSignal(12_000),\n });\n if (!res.ok) throw new Error(`near-intents: deposit notification failed (${res.status})`);\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n const {depositAddress, depositMemo} = decodeIntent(ref.intentId);\n // Durable retry: BaseSwap2Protocol embeds the source hash in the swap2\n // id. If the post-broadcast notify failed, every status poll retries it.\n if (ref.sourceTxHash) {\n await this.notifyDeposit?.(ref.intentId, ref.sourceTxHash).catch(() => {});\n }\n try {\n const query = new URLSearchParams({depositAddress});\n if (depositMemo) query.set(\"depositMemo\", depositMemo);\n const res = await fetch(\n `${apiBase}/status?${query.toString()}`,\n {headers: authHeaders(config.jwt), signal: timeoutSignal(12_000)},\n );\n if (!res.ok) return {state: \"pending\"};\n const s = (await res.json()) as {\n status?: string;\n swapDetails?: {destinationChainTxHashes?: unknown[]};\n };\n const map: Record<string, IntentStatus[\"state\"]> = {\n PENDING_DEPOSIT: \"pending\",\n KNOWN_DEPOSIT_TX: \"pending\",\n INCOMPLETE_DEPOSIT: \"pending\",\n PROCESSING: \"pending\",\n SUCCESS: \"completed\",\n FAILED: \"failed\",\n REFUNDED: \"refunded\",\n };\n const state = map[s.status ?? \"PENDING_DEPOSIT\"] ?? \"pending\";\n // KNOWN_DEPOSIT_TX: 1Click has the deposit tx (submitted, not yet\n // credited). Counted as received so a caller with no source hash of\n // its own does not expire a swap that is already on its way.\n const depositReceived = s.status === \"KNOWN_DEPOSIT_TX\" || s.status === \"PROCESSING\" || s.status === \"INCOMPLETE_DEPOSIT\";\n const destTx = txHashOf(s.swapDetails?.destinationChainTxHashes?.[0]);\n return {state, depositReceived, ...(destTx ? {destTxHash: destTx} : {})};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.cjs
CHANGED
|
@@ -316,6 +316,7 @@ function nearIntentsProvider(config = {}) {
|
|
|
316
316
|
const s = await res.json();
|
|
317
317
|
const map = {
|
|
318
318
|
PENDING_DEPOSIT: "pending",
|
|
319
|
+
KNOWN_DEPOSIT_TX: "pending",
|
|
319
320
|
INCOMPLETE_DEPOSIT: "pending",
|
|
320
321
|
PROCESSING: "pending",
|
|
321
322
|
SUCCESS: "completed",
|
|
@@ -323,7 +324,7 @@ function nearIntentsProvider(config = {}) {
|
|
|
323
324
|
REFUNDED: "refunded"
|
|
324
325
|
};
|
|
325
326
|
const state = map[s.status ?? "PENDING_DEPOSIT"] ?? "pending";
|
|
326
|
-
const depositReceived = s.status === "PROCESSING" || s.status === "INCOMPLETE_DEPOSIT";
|
|
327
|
+
const depositReceived = s.status === "KNOWN_DEPOSIT_TX" || s.status === "PROCESSING" || s.status === "INCOMPLETE_DEPOSIT";
|
|
327
328
|
const destTx = txHashOf(s.swapDetails?.destinationChainTxHashes?.[0]);
|
|
328
329
|
return { state, depositReceived, ...destTx ? { destTxHash: destTx } : {} };
|
|
329
330
|
} catch {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/activity.ts","../src/provider.ts","../src/protocol.ts"],"sourcesContent":["export * from \"./config.js\";\nexport * from \"./provider.js\";\nexport {NearIntentsSwap2Protocol} from \"./protocol.js\";\nexport {NearIntentsSwap2Protocol as default} from \"./protocol.js\";\nexport * from \"./activity.js\";\n","import {namespace} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {ccChain} from \"@anywalletkit/swap2-assets\";\n\n// ── NEAR Intents (1Click) — core, broadest coverage ─────────────────────────\nconst NEAR_INTENTS_NS = new Set([\n \"eip155\", \"solana\", \"tron\", \"bitcoin\", \"near\", \"sui\", \"ton\", \"zcash\",\n \"litecoin\", \"doge\", \"xrp\", \"bch\", \"cardano\", \"stellar\", \"aptos\",\n]);\n\n/**\n * Corridors the APP has paused (caip2 → why), passed in through the provider\n * config: a venue-side degradation (1Click's HOT omni-bridge assets answering\n * \"not available\" for days) is an operational switch, not SDK knowledge — the\n * wallet flips an env var and lifts it the same way when the venue recovers.\n */\nexport type NearIntentsSuspendedChains = Readonly<Record<string, string>>;\n\n/** Why a chain is refused up front, or null when 1Click can serve it. */\nexport function nearIntentsChainRefusal(chain: string, suspended: NearIntentsSuspendedChains = {}): string | null {\n if (!NEAR_INTENTS_NS.has(namespace(chain))) return `1Click does not serve ${chain}`;\n const why = suspended[chain];\n if (why) return `1Click corridor paused by the app: ${chain} — ${why}`;\n // A chain the catalog knows but carries no 1Click asset id for (World Chain,\n // Sei, Ink, Plume, X Layer, Unichain, MegaETH, Linea, Sonic, …) is LI.FI /\n // CCTP territory: the eip155 namespace alone used to claim it, and every\n // quote then died as \"unknown asset\" (2026-10-16 funded run).\n const listed = ccChain(chain)?.assets.some((a) => a.assetId.length > 0) ?? false;\n return listed ? null : `1Click does not list ${chain}`;\n}\n\nexport const nearIntents = {\n enabled: () => true,\n // Routes between any pair of 1Click-listed chains. 1Click is a NEAR-intents\n // solver network — it settles non-EVM↔non-EVM directly (BTC→Solana, Tron→\n // Base …), so this pre-filter must NOT require an EVM leg (the old \"vault\n // leg is always EVM\" assumption of the off-ramp flow silently blocked those\n // swap routes). A chain counts as listed when the shared catalog carries at\n // least one 1Click asset id for it and it is not suspended above; `getQuote`\n // is the real per-pair check and fail-closes (returns null, naming why) for\n // any pair 1Click can't actually route.\n // 2026-08 sweep: 1Click added LTC/DOGE/XRP/BCH/ADA/XLM/APT (+ the EVM\n // additions Avalanche/Scroll/Berachain, covered by the catalog ids).\n supportsChain(chain: string): boolean {\n return nearIntentsChainRefusal(chain) === null;\n },\n supports(from: string, to: string): boolean {\n return this.supportsChain(from) && this.supportsChain(to);\n },\n};\n","/**\n * Activity recognition for NEAR Intents (1Click).\n *\n * The source leg on EVM / TON / Solana / Tron / BTC is a plain transfer to a\n * one-time 1Click deposit address, and the destination leg is a plain transfer\n * from a solver / bridge account that changes per swap — neither carries a\n * stable on-chain marker, so they are NOT recognizable offline. The kit's\n * intent journal (the `intentId` returned by `swap2()`) ties those legs back to\n * the swap; this hook only answers for the legs that do have a fixed\n * counterparty: on NEAR itself, deposits into and withdrawals out of the\n * `intents.near` verifier contract (NEP-141 `ft_transfer_call` / `ft_withdraw`).\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {describeSwapLike} from \"@anywalletkit/protocol-swap2-core/activity\";\n\nexport const NEAR_INTENTS_MODULE = \"@anywalletkit/protocol-swap2-near-intents\";\n\n/** The NEAR Intents verifier / settlement contract. */\nexport const NEAR_INTENTS_CONTRACT = \"intents.near\";\n\nexport function describeNearIntentsActivity(tx: ChainTx, ctx: DescribeActivityContext): ActivityItem | null {\n if (!tx.chain.startsWith(\"near:\")) return null;\n const isOwn = (a: string) => ctx.own.has(a);\n const touches = tx.transfers.some((t) => (t.from === NEAR_INTENTS_CONTRACT && isOwn(t.to)) || (t.to === NEAR_INTENTS_CONTRACT && isOwn(t.from)));\n if (!touches) return null;\n return describeSwapLike(tx, ctx, {\n protocol: NEAR_INTENTS_MODULE,\n subtitle: \"NEAR Intents\",\n kind: \"bridge\",\n counterparty: NEAR_INTENTS_CONTRACT,\n inSuffix: \"via NEAR Intents\",\n });\n}\n","import {nearIntents as cfg, nearIntentsChainRefusal, type NearIntentsSuspendedChains} from \"./config.js\";\nimport {describeNearIntentsActivity} from \"./activity.js\";\nimport {timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {CC_DEST, ccAsset, ccAssetByToken, ccChain} from \"@anywalletkit/swap2-assets\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * NEAR Intents (1Click) provider — the core route, broadest coverage. Ported\n * from a production 1Click integration:\n * dry quote → pricing preview; live quote → depositAddress the user funds\n * from any wallet; status polled by depositAddress.\n * Runs server-side, so the partner JWT stays here (no proxy needed). Defensive:\n * any API error yields a null quote so the provider drops out of that round.\n */\n\nconst ONE_CLICK_DEFAULT = \"https://1click.chaindefuser.com/v0\";\nconst QUOTE_TTL_MS = 55_000;\n\n/** intentId durably carries both status lookup keys (memo is quote-specific). */\nconst INTENT_PREFIX = \"near1click:\";\n\nfunction encodeIntent(depositAddress: string, depositMemo: string | null): string {\n return `${INTENT_PREFIX}${encodeURIComponent(depositAddress)}|${encodeURIComponent(depositMemo ?? \"\")}`;\n}\n\nfunction decodeIntent(intentId: string): {depositAddress: string; depositMemo?: string} {\n try {\n if (!intentId.startsWith(INTENT_PREFIX)) throw new Error(\"unsupported id version\");\n const raw = intentId.slice(INTENT_PREFIX.length);\n const parts = raw.split(\"|\");\n if (parts.length !== 2 || !parts[0]) throw new Error(\"invalid id shape\");\n const depositAddress = decodeURIComponent(parts[0]);\n const memo = decodeURIComponent(parts[1] ?? \"\");\n if (!depositAddress) throw new Error(\"empty deposit address\");\n return {depositAddress, ...(memo ? {depositMemo: memo} : {})};\n } catch {\n throw new Error(\"near-intents: malformed intent id\");\n }\n}\n\nfunction authHeaders(jwtOverride?: string): Record<string, string> {\n const h: Record<string, string> = {\"content-type\": \"application/json\", accept: \"application/json\"};\n const jwt = jwtOverride;\n if (jwt) h.authorization = `Bearer ${jwt}`;\n return h;\n}\n\n/** Our integrator fee, injected server-side when a recipient is configured. */\nfunction appFees(recipient?: string, bps?: number): {recipient: string; fee: number}[] | undefined {\n return recipient !== undefined && bps !== undefined ? [{recipient, fee: bps}] : undefined;\n}\n\n/**\n * Per-source deposit + refund config. Every live default keeps failed-swap\n * ownership on the caller's source-chain address.\n */\nfunction depositConfig(_sourceChain: string, refundAddress: string, _dry: boolean) {\n // Every source refunds to the caller's own source-chain address (Zcash\n // included — a t-address placeholder serves dry quotes since 2026-10-18).\n // Never redirect failed swaps to an integrator-owned NEAR account.\n return {depositType: \"ORIGIN_CHAIN\", refundType: \"ORIGIN_CHAIN\", refundTo: refundAddress};\n}\n\n/** Placeholder sender/recipient for dry quotes (1Click requires the fields). */\nconst PLACEHOLDER: Record<string, string> = {\n bitcoin: \"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq\",\n ton: \"UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ\",\n // NOT a token mint: with the USDC mint here, every dry quote whose ORIGIN\n // was Solana USDC answered 500 \"Internal server error\" (2026-10-09) — a\n // refund \"to the asset's own mint\" trips 1Click. The incinerator is a\n // plain, valid system address.\n solana: \"1nc1nerator11111111111111111111111111111111\",\n tron: \"TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9\",\n // NEAR refunds go to an account id; the registrar account always exists.\n near: \"near\",\n // A live transparent address (exchange hot wallet); dry quotes only.\n zcash: \"t1KfwsnwJeNRVjQGBDZhwKskpQbih2qx5Ua\",\n eip155: \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",\n};\n\nfunction placeholderFor(chain: string): string {\n return PLACEHOLDER[chain.split(\":\")[0] ?? \"\"] ?? PLACEHOLDER.eip155!;\n}\n\nfunction deadlineIn(minutes: number): string {\n return new Date(Date.now() + minutes * 60_000).toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n}\n\n/**\n * dest asset id for ANY chain in the catalog (inbound → Ethereum, or the step-2\n * off-ramp → any supported chain). Falls back to the Ethereum omft pattern for\n * a mainnet ERC-20 that isn't in the curated catalog.\n */\nfunction destAssetId(destChain: string, destToken: string): string | null {\n const asset = ccAssetByToken(destChain, destToken);\n if (asset) return asset.assetId;\n if (destChain === CC_DEST.caip2 && /^0x[0-9a-fA-F]{40}$/.test(destToken)) {\n return `nep141:eth-${destToken.toLowerCase()}.omft.near`;\n }\n return null;\n}\n\ntype OneClickQuote = {\n quote?: Record<string, unknown>;\n correlationId?: string;\n error?: string;\n message?: string;\n};\n\n/** 1Click returns tx hashes either as strings or {hash, explorerUrl}. */\nfunction txHashOf(entry: unknown): string | null {\n if (!entry) return null;\n if (typeof entry === \"string\") return entry;\n const h = (entry as {hash?: string}).hash;\n return typeof h === \"string\" ? h : null;\n}\n\n/** Explicit constructor configuration; no deployment environment is read. */\nexport interface NearIntentsProviderConfig {\n enabled?: boolean;\n apiUrl?: string;\n jwt?: string;\n feeRecipient?: string;\n feeBps?: number;\n /** Corridors the app has paused (caip2 → reason): refused up front, by name, until the app lifts them. */\n suspendedChains?: NearIntentsSuspendedChains;\n}\n\nexport function nearIntentsProvider(config: NearIntentsProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const parsedApiUrl = new URL(config.apiUrl ?? ONE_CLICK_DEFAULT);\n if (parsedApiUrl.protocol !== \"https:\" && parsedApiUrl.protocol !== \"http:\") {\n throw new Error(\"near-intents: apiUrl must use http or https\");\n }\n const apiBase = parsedApiUrl.toString().replace(/\\/$/, \"\");\n const hasRecipient = config.feeRecipient !== undefined;\n const hasBps = config.feeBps !== undefined;\n if (hasRecipient !== hasBps) throw new Error(\"near-intents: feeRecipient and feeBps must be configured together\");\n if (hasRecipient && (!config.feeRecipient!.trim() || !Number.isInteger(config.feeBps) || config.feeBps! <= 0 || config.feeBps! > 10_000)) {\n throw new Error(\"near-intents: fee config requires a recipient and feeBps between 1 and 10000\");\n }\n return {\n name: \"near_intents\",\n describeActivity: describeNearIntentsActivity,\n enabled: () => config.enabled ?? true,\n\n // Capability discovery comes from the provider itself, so it can run alone\n // or inside the optional aggregator without a central capability table.\n supportsChain: (chain: string) => cfg.supportsChain(chain),\n supportsChainPair: (fromChain: string, toChain: string) => cfg.supports(fromChain, toChain),\n supportsRoute(from: Asset, to: Asset): boolean {\n // Chain-level gate first (namespace, catalog listing, hand-suspended\n // corridors such as TON while the HOT bridge is dark) …\n if (!cfg.supports(from.chain, to.chain)) return false;\n // … then only pairs present in the curated catalog are offered — and only\n // those with a 1Click asset id (LI.FI-only tokens carry an empty assetId).\n // Both ends: a destination 1Click doesn't list (Unichain, MegaETH, …)\n // answered \"unknown asset\" on every quote (589 of the 2026-10-10 matrix).\n const asset = ccAsset(from.chain, from.token);\n return !!ccChain(from.chain) && !!asset?.assetId && !!destAssetId(to.chain, to.token);\n },\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n // Every refusal below names itself: on the server these lines are the\n // only visibility into WHY a live quote returned null (the wire answer\n // is just `null`), and \"no route\" bugs hide in exactly that silence.\n const refuse = (reason: string): null => {\n const detail = `${reason} [dry=${params.dry !== false} ${params.sourceChain}->${params.destChain} amount=${params.amountIn}]`;\n // Caller fields and 1Click text are untrusted: no control characters in server logs.\n console.warn(`near-intents: no quote — ${detail.replace(/[\\u0000-\\u001f\\u007f]/g, \" \")}`);\n params.onRefusal?.(detail);\n return null;\n };\n // Up-front, named refusals — no wire call for a corridor 1Click cannot\n // serve: a chain outside its list / suspended by hand, or a token the\n // catalog carries without a 1Click asset id (\"1Click does not list …\").\n const paused = config.suspendedChains ?? {};\n const chainRefusal = nearIntentsChainRefusal(params.sourceChain, paused) ?? nearIntentsChainRefusal(params.destChain, paused);\n if (chainRefusal) return refuse(chainRefusal);\n const origin = ccAsset(params.sourceChain, params.sourceToken);\n if (!origin?.assetId) return refuse(`1Click does not list ${params.sourceChain} ${params.sourceToken}`);\n const destination = destAssetId(params.destChain, params.destToken);\n if (!destination) return refuse(`1Click does not list ${params.destChain} ${params.destToken}`);\n const dry = params.dry !== false;\n // A live quote derives the deposit address from the refund config —\n // never create one without a real refund destination.\n const refund = params.refundAddress ?? (dry ? placeholderFor(params.sourceChain) : \"\");\n const dcfg = depositConfig(params.sourceChain, refund, dry);\n if (!dry && !dcfg.refundTo) return refuse(\"live quote without a refund address\");\n\n const requestedDeadline = deadlineIn(60);\n const body: Record<string, unknown> = {\n dry,\n // FLEX_INPUT (exchange flow): the address accepts any amount; amountIn\n // is just the pricing notional. Verified against the live API.\n swapType: params.flex ? \"FLEX_INPUT\" : \"EXACT_INPUT\",\n slippageTolerance: params.slippageBps ?? 100,\n originAsset: origin.assetId,\n depositType: dcfg.depositType,\n destinationAsset: destination,\n amount: params.amountIn,\n refundTo: dcfg.refundTo,\n refundType: dcfg.refundType,\n recipient: params.destAddress,\n recipientType: \"DESTINATION_CHAIN\",\n deadline: requestedDeadline,\n };\n const fees = appFees(config.feeRecipient, config.feeBps);\n if (fees) body.appFees = fees;\n\n try {\n // 1Click's solver auction flaps: the same body can answer 400 \"No\n // liquidity available\" and 201 seconds apart (observed live on\n // TON USDT -> ETH). A transient flap on the EXECUTION quote would\n // surface as a terminal \"no route\" right after a successful display\n // quote, so ride through it: up to two retries on liquidity flaps,\n // 5xx and network errors. Real rejections (bad address, unknown\n // asset) still fail on the first answer.\n let res: Response | null = null;\n let data: OneClickQuote = {};\n for (let attempt = 0; ; attempt++) {\n try {\n res = await fetch(`${apiBase}/quote`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify(body),\n signal: signal ?? timeoutSignal(12_000),\n });\n data = (await res.json().catch(() => ({}))) as OneClickQuote;\n } catch (err) {\n if (attempt >= 2 || signal?.aborted) throw err;\n res = null;\n }\n if (res?.ok) break;\n const flaky =\n res === null ||\n res.status >= 500 ||\n (res.status === 400 && /no liquidity/i.test(String(data.message ?? \"\")));\n if (!flaky || attempt >= 2 || signal?.aborted) break;\n await new Promise((resolve) => setTimeout(resolve, 500 * (attempt + 1)));\n }\n if (!res?.ok) return refuse(`1Click ${res?.status ?? \"network error\"}: ${String(data.message ?? \"\").slice(0, 200)}`);\n const q = (data.quote ?? {}) as Record<string, unknown>;\n\n const depositAddress = typeof q.depositAddress === \"string\" ? q.depositAddress : \"\";\n if (!dry && !depositAddress) return refuse(\"live quote came back without a deposit address\");\n const inUsd = Number.parseFloat(String(q.amountInUsd ?? \"0\"));\n const outUsd = Number.parseFloat(String(q.amountOutUsd ?? \"0\"));\n const parsedDeadline = Date.parse(String(q.deadline ?? \"\"));\n if (!dry && (!Number.isFinite(parsedDeadline) || parsedDeadline <= Date.now())) return refuse(`unusable deadline ${String(q.deadline)}`);\n const deadline = Number.isFinite(parsedDeadline) && parsedDeadline > Date.now()\n ? Math.min(parsedDeadline, Date.now() + QUOTE_TTL_MS)\n : Date.now() + QUOTE_TTL_MS;\n\n if (q.amountIn !== undefined && String(q.amountIn) !== params.amountIn) return refuse(`amountIn mismatch (${String(q.amountIn)} vs ${params.amountIn})`);\n\n // amountOut is optimistic, not a guaranteed floor. Live execution must\n // not fabricate a minimum when the provider omits it.\n if (q.minAmountOut === undefined || q.minAmountOut === null) return refuse(\"quote has no minAmountOut\");\n const minDestAmount = String(q.minAmountOut);\n if (params.minAmountOut !== undefined && BigInt(minDestAmount) < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${minDestAmount} < floor=${params.minAmountOut})`);\n const depositMemo =\n (typeof q.depositMemo === \"string\" && q.depositMemo) ||\n (typeof q.memo === \"string\" && q.memo) ||\n null;\n return {\n provider: \"near_intents\",\n intentId: depositAddress ? encodeIntent(depositAddress, depositMemo) : `dry:${crypto.randomUUID()}`,\n depositAddress,\n depositMemo,\n sourceAmount: params.amountIn,\n destAmount: String(q.amountOut ?? \"0\"),\n minDestAmount,\n feeUsd: Math.max(0, inUsd - outUsd),\n etaSeconds: Number(q.timeEstimate ?? 60),\n reliability: 0.95,\n validUntilMs: deadline,\n };\n } catch (err) {\n return refuse(`threw: ${err instanceof Error ? err.message.slice(0, 200) : String(err).slice(0, 200)}`);\n }\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n return {\n chain: \"\",\n to: quote.depositAddress,\n value: quote.sourceAmount,\n ...(quote.depositMemo ? {memo: quote.depositMemo} : {}),\n };\n },\n\n async notifyDeposit(intentId: string, txHash: string): Promise<void> {\n const {depositAddress} = decodeIntent(intentId);\n const res = await fetch(`${apiBase}/deposit/submit`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify({depositAddress, txHash}),\n signal: timeoutSignal(12_000),\n });\n if (!res.ok) throw new Error(`near-intents: deposit notification failed (${res.status})`);\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n const {depositAddress, depositMemo} = decodeIntent(ref.intentId);\n // Durable retry: BaseSwap2Protocol embeds the source hash in the swap2\n // id. If the post-broadcast notify failed, every status poll retries it.\n if (ref.sourceTxHash) {\n await this.notifyDeposit?.(ref.intentId, ref.sourceTxHash).catch(() => {});\n }\n try {\n const query = new URLSearchParams({depositAddress});\n if (depositMemo) query.set(\"depositMemo\", depositMemo);\n const res = await fetch(\n `${apiBase}/status?${query.toString()}`,\n {headers: authHeaders(config.jwt), signal: timeoutSignal(12_000)},\n );\n if (!res.ok) return {state: \"pending\"};\n const s = (await res.json()) as {\n status?: string;\n swapDetails?: {destinationChainTxHashes?: unknown[]};\n };\n const map: Record<string, IntentStatus[\"state\"]> = {\n PENDING_DEPOSIT: \"pending\",\n INCOMPLETE_DEPOSIT: \"pending\",\n PROCESSING: \"pending\",\n SUCCESS: \"completed\",\n FAILED: \"failed\",\n REFUNDED: \"refunded\",\n };\n const state = map[s.status ?? \"PENDING_DEPOSIT\"] ?? \"pending\";\n const depositReceived = s.status === \"PROCESSING\" || s.status === \"INCOMPLETE_DEPOSIT\";\n const destTx = txHashOf(s.swapDetails?.destinationChainTxHashes?.[0]);\n return {state, depositReceived, ...(destTx ? {destTxHash: destTx} : {})};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n","import {SingleProviderSwap2} from \"@anywalletkit/protocol-swap2-core/swap2/single\";\nimport type {Swap2Account, Swap2EngineConfig} from \"@anywalletkit/protocol-swap2-core/swap2/base\";\nimport {nearIntents as nearIntentsCfg} from \"./config.js\";\nimport {nearIntentsProvider, type NearIntentsProviderConfig} from \"./provider.js\";\n\nexport interface NearIntentsSwap2Config extends Swap2EngineConfig, NearIntentsProviderConfig {}\n\nexport class NearIntentsSwap2Protocol extends SingleProviderSwap2 {\n protected readonly provider;\n constructor(account: Swap2Account | undefined, config: NearIntentsSwap2Config) {\n super(account, config);\n this.provider = nearIntentsProvider(config);\n }\n protected override chainSupported(caip2: string): boolean {\n return nearIntentsCfg.supports(caip2, \"eip155:1\") || nearIntentsCfg.supports(\"eip155:1\", caip2);\n }\n protected override pairSupported(fromChain: string, toChain: string): boolean {\n return nearIntentsCfg.supports(fromChain, toChain);\n }\n}\n"],"mappings":"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","names":["import_util","import_swap2_assets"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/activity.ts","../src/provider.ts","../src/protocol.ts"],"sourcesContent":["export * from \"./config.js\";\nexport * from \"./provider.js\";\nexport {NearIntentsSwap2Protocol} from \"./protocol.js\";\nexport {NearIntentsSwap2Protocol as default} from \"./protocol.js\";\nexport * from \"./activity.js\";\nexport type { NearIntentsSwap2Config } from \"./protocol.js\"\n","import {namespace} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {ccChain} from \"@anywalletkit/swap2-assets\";\n\n// ── NEAR Intents (1Click) — core, broadest coverage ─────────────────────────\nconst NEAR_INTENTS_NS = new Set([\n \"eip155\", \"solana\", \"tron\", \"bitcoin\", \"near\", \"sui\", \"ton\", \"zcash\",\n \"litecoin\", \"doge\", \"xrp\", \"bch\", \"cardano\", \"stellar\", \"aptos\",\n]);\n\n/**\n * Corridors the APP has paused (caip2 → why), passed in through the provider\n * config: a venue-side degradation (1Click's HOT omni-bridge assets answering\n * \"not available\" for days) is an operational switch, not SDK knowledge — the\n * wallet flips an env var and lifts it the same way when the venue recovers.\n */\nexport type NearIntentsSuspendedChains = Readonly<Record<string, string>>;\n\n/** Why a chain is refused up front, or null when 1Click can serve it. */\nexport function nearIntentsChainRefusal(chain: string, suspended: NearIntentsSuspendedChains = {}): string | null {\n if (!NEAR_INTENTS_NS.has(namespace(chain))) return `1Click does not serve ${chain}`;\n const why = suspended[chain];\n if (why) return `1Click corridor paused by the app: ${chain} — ${why}`;\n // A chain the catalog knows but carries no 1Click asset id for (World Chain,\n // Sei, Ink, Plume, X Layer, Unichain, MegaETH, Linea, Sonic, …) is LI.FI /\n // CCTP territory: the eip155 namespace alone used to claim it, and every\n // quote then died as \"unknown asset\" (2026-10-16 funded run).\n const listed = ccChain(chain)?.assets.some((a) => a.assetId.length > 0) ?? false;\n return listed ? null : `1Click does not list ${chain}`;\n}\n\nexport const nearIntents = {\n enabled: () => true,\n // Routes between any pair of 1Click-listed chains. 1Click is a NEAR-intents\n // solver network — it settles non-EVM↔non-EVM directly (BTC→Solana, Tron→\n // Base …), so this pre-filter must NOT require an EVM leg (the old \"vault\n // leg is always EVM\" assumption of the off-ramp flow silently blocked those\n // swap routes). A chain counts as listed when the shared catalog carries at\n // least one 1Click asset id for it and it is not suspended above; `getQuote`\n // is the real per-pair check and fail-closes (returns null, naming why) for\n // any pair 1Click can't actually route.\n // 2026-08 sweep: 1Click added LTC/DOGE/XRP/BCH/ADA/XLM/APT (+ the EVM\n // additions Avalanche/Scroll/Berachain, covered by the catalog ids).\n supportsChain(chain: string): boolean {\n return nearIntentsChainRefusal(chain) === null;\n },\n supports(from: string, to: string): boolean {\n return this.supportsChain(from) && this.supportsChain(to);\n },\n};\n","/**\n * Activity recognition for NEAR Intents (1Click).\n *\n * The source leg on EVM / TON / Solana / Tron / BTC is a plain transfer to a\n * one-time 1Click deposit address, and the destination leg is a plain transfer\n * from a solver / bridge account that changes per swap — neither carries a\n * stable on-chain marker, so they are NOT recognizable offline. The kit's\n * intent journal (the `intentId` returned by `swap2()`) ties those legs back to\n * the swap; this hook only answers for the legs that do have a fixed\n * counterparty: on NEAR itself, deposits into and withdrawals out of the\n * `intents.near` verifier contract (NEP-141 `ft_transfer_call` / `ft_withdraw`).\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {describeSwapLike} from \"@anywalletkit/protocol-swap2-core/activity\";\n\nexport const NEAR_INTENTS_MODULE = \"@anywalletkit/protocol-swap2-near-intents\";\n\n/** The NEAR Intents verifier / settlement contract. */\nexport const NEAR_INTENTS_CONTRACT = \"intents.near\";\n\nexport function describeNearIntentsActivity(tx: ChainTx, ctx: DescribeActivityContext): ActivityItem | null {\n if (!tx.chain.startsWith(\"near:\")) return null;\n const isOwn = (a: string) => ctx.own.has(a);\n const touches = tx.transfers.some((t) => (t.from === NEAR_INTENTS_CONTRACT && isOwn(t.to)) || (t.to === NEAR_INTENTS_CONTRACT && isOwn(t.from)));\n if (!touches) return null;\n return describeSwapLike(tx, ctx, {\n protocol: NEAR_INTENTS_MODULE,\n subtitle: \"NEAR Intents\",\n kind: \"bridge\",\n counterparty: NEAR_INTENTS_CONTRACT,\n inSuffix: \"via NEAR Intents\",\n });\n}\n","import {nearIntents as cfg, nearIntentsChainRefusal, type NearIntentsSuspendedChains} from \"./config.js\";\nimport {describeNearIntentsActivity} from \"./activity.js\";\nimport {timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {CC_DEST, ccAsset, ccAssetByToken, ccChain} from \"@anywalletkit/swap2-assets\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * NEAR Intents (1Click) provider — the core route, broadest coverage. Ported\n * from a production 1Click integration:\n * dry quote → pricing preview; live quote → depositAddress the user funds\n * from any wallet; status polled by depositAddress.\n * Runs server-side, so the partner JWT stays here (no proxy needed). Defensive:\n * any API error yields a null quote so the provider drops out of that round.\n */\n\nconst ONE_CLICK_DEFAULT = \"https://1click.chaindefuser.com/v0\";\nconst QUOTE_TTL_MS = 55_000;\n\n/** intentId durably carries both status lookup keys (memo is quote-specific). */\nconst INTENT_PREFIX = \"near1click:\";\n\nfunction encodeIntent(depositAddress: string, depositMemo: string | null): string {\n return `${INTENT_PREFIX}${encodeURIComponent(depositAddress)}|${encodeURIComponent(depositMemo ?? \"\")}`;\n}\n\nfunction decodeIntent(intentId: string): {depositAddress: string; depositMemo?: string} {\n try {\n if (!intentId.startsWith(INTENT_PREFIX)) throw new Error(\"unsupported id version\");\n const raw = intentId.slice(INTENT_PREFIX.length);\n const parts = raw.split(\"|\");\n if (parts.length !== 2 || !parts[0]) throw new Error(\"invalid id shape\");\n const depositAddress = decodeURIComponent(parts[0]);\n const memo = decodeURIComponent(parts[1] ?? \"\");\n if (!depositAddress) throw new Error(\"empty deposit address\");\n return {depositAddress, ...(memo ? {depositMemo: memo} : {})};\n } catch {\n throw new Error(\"near-intents: malformed intent id\");\n }\n}\n\nfunction authHeaders(jwtOverride?: string): Record<string, string> {\n const h: Record<string, string> = {\"content-type\": \"application/json\", accept: \"application/json\"};\n const jwt = jwtOverride;\n if (jwt) h.authorization = `Bearer ${jwt}`;\n return h;\n}\n\n/** Our integrator fee, injected server-side when a recipient is configured. */\nfunction appFees(recipient?: string, bps?: number): {recipient: string; fee: number}[] | undefined {\n return recipient !== undefined && bps !== undefined ? [{recipient, fee: bps}] : undefined;\n}\n\n/**\n * Per-source deposit + refund config. Every live default keeps failed-swap\n * ownership on the caller's source-chain address.\n */\nfunction depositConfig(_sourceChain: string, refundAddress: string, _dry: boolean) {\n // Every source refunds to the caller's own source-chain address (Zcash\n // included — a t-address placeholder serves dry quotes since 2026-10-18).\n // Never redirect failed swaps to an integrator-owned NEAR account.\n return {depositType: \"ORIGIN_CHAIN\", refundType: \"ORIGIN_CHAIN\", refundTo: refundAddress};\n}\n\n/** Placeholder sender/recipient for dry quotes (1Click requires the fields). */\nconst PLACEHOLDER: Record<string, string> = {\n bitcoin: \"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq\",\n ton: \"UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ\",\n // NOT a token mint: with the USDC mint here, every dry quote whose ORIGIN\n // was Solana USDC answered 500 \"Internal server error\" (2026-10-09) — a\n // refund \"to the asset's own mint\" trips 1Click. The incinerator is a\n // plain, valid system address.\n solana: \"1nc1nerator11111111111111111111111111111111\",\n tron: \"TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9\",\n // NEAR refunds go to an account id; the registrar account always exists.\n near: \"near\",\n // A live transparent address (exchange hot wallet); dry quotes only.\n zcash: \"t1KfwsnwJeNRVjQGBDZhwKskpQbih2qx5Ua\",\n eip155: \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",\n};\n\nfunction placeholderFor(chain: string): string {\n return PLACEHOLDER[chain.split(\":\")[0] ?? \"\"] ?? PLACEHOLDER.eip155!;\n}\n\nfunction deadlineIn(minutes: number): string {\n return new Date(Date.now() + minutes * 60_000).toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n}\n\n/**\n * dest asset id for ANY chain in the catalog (inbound → Ethereum, or the step-2\n * off-ramp → any supported chain). Falls back to the Ethereum omft pattern for\n * a mainnet ERC-20 that isn't in the curated catalog.\n */\nfunction destAssetId(destChain: string, destToken: string): string | null {\n const asset = ccAssetByToken(destChain, destToken);\n if (asset) return asset.assetId;\n if (destChain === CC_DEST.caip2 && /^0x[0-9a-fA-F]{40}$/.test(destToken)) {\n return `nep141:eth-${destToken.toLowerCase()}.omft.near`;\n }\n return null;\n}\n\ntype OneClickQuote = {\n quote?: Record<string, unknown>;\n correlationId?: string;\n error?: string;\n message?: string;\n};\n\n/** 1Click returns tx hashes either as strings or {hash, explorerUrl}. */\nfunction txHashOf(entry: unknown): string | null {\n if (!entry) return null;\n if (typeof entry === \"string\") return entry;\n const h = (entry as {hash?: string}).hash;\n return typeof h === \"string\" ? h : null;\n}\n\n/** Explicit constructor configuration; no deployment environment is read. */\nexport interface NearIntentsProviderConfig {\n enabled?: boolean;\n apiUrl?: string;\n jwt?: string;\n feeRecipient?: string;\n feeBps?: number;\n /** Corridors the app has paused (caip2 → reason): refused up front, by name, until the app lifts them. */\n suspendedChains?: NearIntentsSuspendedChains;\n}\n\nexport function nearIntentsProvider(config: NearIntentsProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const parsedApiUrl = new URL(config.apiUrl ?? ONE_CLICK_DEFAULT);\n if (parsedApiUrl.protocol !== \"https:\" && parsedApiUrl.protocol !== \"http:\") {\n throw new Error(\"near-intents: apiUrl must use http or https\");\n }\n const apiBase = parsedApiUrl.toString().replace(/\\/$/, \"\");\n const hasRecipient = config.feeRecipient !== undefined;\n const hasBps = config.feeBps !== undefined;\n if (hasRecipient !== hasBps) throw new Error(\"near-intents: feeRecipient and feeBps must be configured together\");\n if (hasRecipient && (!config.feeRecipient!.trim() || !Number.isInteger(config.feeBps) || config.feeBps! <= 0 || config.feeBps! > 10_000)) {\n throw new Error(\"near-intents: fee config requires a recipient and feeBps between 1 and 10000\");\n }\n return {\n name: \"near_intents\",\n describeActivity: describeNearIntentsActivity,\n enabled: () => config.enabled ?? true,\n\n // Capability discovery comes from the provider itself, so it can run alone\n // or inside the optional aggregator without a central capability table.\n supportsChain: (chain: string) => cfg.supportsChain(chain),\n supportsChainPair: (fromChain: string, toChain: string) => cfg.supports(fromChain, toChain),\n supportsRoute(from: Asset, to: Asset): boolean {\n // Chain-level gate first (namespace, catalog listing, hand-suspended\n // corridors such as TON while the HOT bridge is dark) …\n if (!cfg.supports(from.chain, to.chain)) return false;\n // … then only pairs present in the curated catalog are offered — and only\n // those with a 1Click asset id (LI.FI-only tokens carry an empty assetId).\n // Both ends: a destination 1Click doesn't list (Unichain, MegaETH, …)\n // answered \"unknown asset\" on every quote (589 of the 2026-10-10 matrix).\n const asset = ccAsset(from.chain, from.token);\n return !!ccChain(from.chain) && !!asset?.assetId && !!destAssetId(to.chain, to.token);\n },\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n // Every refusal below names itself: on the server these lines are the\n // only visibility into WHY a live quote returned null (the wire answer\n // is just `null`), and \"no route\" bugs hide in exactly that silence.\n const refuse = (reason: string): null => {\n const detail = `${reason} [dry=${params.dry !== false} ${params.sourceChain}->${params.destChain} amount=${params.amountIn}]`;\n // Caller fields and 1Click text are untrusted: no control characters in server logs.\n console.warn(`near-intents: no quote — ${detail.replace(/[\\u0000-\\u001f\\u007f]/g, \" \")}`);\n params.onRefusal?.(detail);\n return null;\n };\n // Up-front, named refusals — no wire call for a corridor 1Click cannot\n // serve: a chain outside its list / suspended by hand, or a token the\n // catalog carries without a 1Click asset id (\"1Click does not list …\").\n const paused = config.suspendedChains ?? {};\n const chainRefusal = nearIntentsChainRefusal(params.sourceChain, paused) ?? nearIntentsChainRefusal(params.destChain, paused);\n if (chainRefusal) return refuse(chainRefusal);\n const origin = ccAsset(params.sourceChain, params.sourceToken);\n if (!origin?.assetId) return refuse(`1Click does not list ${params.sourceChain} ${params.sourceToken}`);\n const destination = destAssetId(params.destChain, params.destToken);\n if (!destination) return refuse(`1Click does not list ${params.destChain} ${params.destToken}`);\n const dry = params.dry !== false;\n // A live quote derives the deposit address from the refund config —\n // never create one without a real refund destination.\n const refund = params.refundAddress ?? (dry ? placeholderFor(params.sourceChain) : \"\");\n const dcfg = depositConfig(params.sourceChain, refund, dry);\n if (!dry && !dcfg.refundTo) return refuse(\"live quote without a refund address\");\n\n const requestedDeadline = deadlineIn(60);\n const body: Record<string, unknown> = {\n dry,\n // FLEX_INPUT (exchange flow): the address accepts any amount; amountIn\n // is just the pricing notional. Verified against the live API.\n swapType: params.flex ? \"FLEX_INPUT\" : \"EXACT_INPUT\",\n slippageTolerance: params.slippageBps ?? 100,\n originAsset: origin.assetId,\n depositType: dcfg.depositType,\n destinationAsset: destination,\n amount: params.amountIn,\n refundTo: dcfg.refundTo,\n refundType: dcfg.refundType,\n recipient: params.destAddress,\n recipientType: \"DESTINATION_CHAIN\",\n deadline: requestedDeadline,\n };\n const fees = appFees(config.feeRecipient, config.feeBps);\n if (fees) body.appFees = fees;\n\n try {\n // 1Click's solver auction flaps: the same body can answer 400 \"No\n // liquidity available\" and 201 seconds apart (observed live on\n // TON USDT -> ETH). A transient flap on the EXECUTION quote would\n // surface as a terminal \"no route\" right after a successful display\n // quote, so ride through it: up to two retries on liquidity flaps,\n // 5xx and network errors. Real rejections (bad address, unknown\n // asset) still fail on the first answer.\n let res: Response | null = null;\n let data: OneClickQuote = {};\n for (let attempt = 0; ; attempt++) {\n try {\n res = await fetch(`${apiBase}/quote`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify(body),\n signal: signal ?? timeoutSignal(12_000),\n });\n data = (await res.json().catch(() => ({}))) as OneClickQuote;\n } catch (err) {\n if (attempt >= 2 || signal?.aborted) throw err;\n res = null;\n }\n if (res?.ok) break;\n const flaky =\n res === null ||\n res.status >= 500 ||\n (res.status === 400 && /no liquidity/i.test(String(data.message ?? \"\")));\n if (!flaky || attempt >= 2 || signal?.aborted) break;\n await new Promise((resolve) => setTimeout(resolve, 500 * (attempt + 1)));\n }\n if (!res?.ok) return refuse(`1Click ${res?.status ?? \"network error\"}: ${String(data.message ?? \"\").slice(0, 200)}`);\n const q = (data.quote ?? {}) as Record<string, unknown>;\n\n const depositAddress = typeof q.depositAddress === \"string\" ? q.depositAddress : \"\";\n if (!dry && !depositAddress) return refuse(\"live quote came back without a deposit address\");\n const inUsd = Number.parseFloat(String(q.amountInUsd ?? \"0\"));\n const outUsd = Number.parseFloat(String(q.amountOutUsd ?? \"0\"));\n const parsedDeadline = Date.parse(String(q.deadline ?? \"\"));\n if (!dry && (!Number.isFinite(parsedDeadline) || parsedDeadline <= Date.now())) return refuse(`unusable deadline ${String(q.deadline)}`);\n const deadline = Number.isFinite(parsedDeadline) && parsedDeadline > Date.now()\n ? Math.min(parsedDeadline, Date.now() + QUOTE_TTL_MS)\n : Date.now() + QUOTE_TTL_MS;\n\n if (q.amountIn !== undefined && String(q.amountIn) !== params.amountIn) return refuse(`amountIn mismatch (${String(q.amountIn)} vs ${params.amountIn})`);\n\n // amountOut is optimistic, not a guaranteed floor. Live execution must\n // not fabricate a minimum when the provider omits it.\n if (q.minAmountOut === undefined || q.minAmountOut === null) return refuse(\"quote has no minAmountOut\");\n const minDestAmount = String(q.minAmountOut);\n if (params.minAmountOut !== undefined && BigInt(minDestAmount) < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${minDestAmount} < floor=${params.minAmountOut})`);\n const depositMemo =\n (typeof q.depositMemo === \"string\" && q.depositMemo) ||\n (typeof q.memo === \"string\" && q.memo) ||\n null;\n return {\n provider: \"near_intents\",\n intentId: depositAddress ? encodeIntent(depositAddress, depositMemo) : `dry:${crypto.randomUUID()}`,\n depositAddress,\n depositMemo,\n sourceAmount: params.amountIn,\n destAmount: String(q.amountOut ?? \"0\"),\n minDestAmount,\n feeUsd: Math.max(0, inUsd - outUsd),\n etaSeconds: Number(q.timeEstimate ?? 60),\n reliability: 0.95,\n validUntilMs: deadline,\n };\n } catch (err) {\n return refuse(`threw: ${err instanceof Error ? err.message.slice(0, 200) : String(err).slice(0, 200)}`);\n }\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n return {\n chain: \"\",\n to: quote.depositAddress,\n value: quote.sourceAmount,\n ...(quote.depositMemo ? {memo: quote.depositMemo} : {}),\n };\n },\n\n async notifyDeposit(intentId: string, txHash: string): Promise<void> {\n const {depositAddress} = decodeIntent(intentId);\n const res = await fetch(`${apiBase}/deposit/submit`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify({depositAddress, txHash}),\n signal: timeoutSignal(12_000),\n });\n if (!res.ok) throw new Error(`near-intents: deposit notification failed (${res.status})`);\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n const {depositAddress, depositMemo} = decodeIntent(ref.intentId);\n // Durable retry: BaseSwap2Protocol embeds the source hash in the swap2\n // id. If the post-broadcast notify failed, every status poll retries it.\n if (ref.sourceTxHash) {\n await this.notifyDeposit?.(ref.intentId, ref.sourceTxHash).catch(() => {});\n }\n try {\n const query = new URLSearchParams({depositAddress});\n if (depositMemo) query.set(\"depositMemo\", depositMemo);\n const res = await fetch(\n `${apiBase}/status?${query.toString()}`,\n {headers: authHeaders(config.jwt), signal: timeoutSignal(12_000)},\n );\n if (!res.ok) return {state: \"pending\"};\n const s = (await res.json()) as {\n status?: string;\n swapDetails?: {destinationChainTxHashes?: unknown[]};\n };\n const map: Record<string, IntentStatus[\"state\"]> = {\n PENDING_DEPOSIT: \"pending\",\n KNOWN_DEPOSIT_TX: \"pending\",\n INCOMPLETE_DEPOSIT: \"pending\",\n PROCESSING: \"pending\",\n SUCCESS: \"completed\",\n FAILED: \"failed\",\n REFUNDED: \"refunded\",\n };\n const state = map[s.status ?? \"PENDING_DEPOSIT\"] ?? \"pending\";\n // KNOWN_DEPOSIT_TX: 1Click has the deposit tx (submitted, not yet\n // credited). Counted as received so a caller with no source hash of\n // its own does not expire a swap that is already on its way.\n const depositReceived = s.status === \"KNOWN_DEPOSIT_TX\" || s.status === \"PROCESSING\" || s.status === \"INCOMPLETE_DEPOSIT\";\n const destTx = txHashOf(s.swapDetails?.destinationChainTxHashes?.[0]);\n return {state, depositReceived, ...(destTx ? {destTxHash: destTx} : {})};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n","import {SingleProviderSwap2} from \"@anywalletkit/protocol-swap2-core/swap2/single\";\nimport type {Swap2Account, Swap2EngineConfig} from \"@anywalletkit/protocol-swap2-core/swap2/base\";\nimport {nearIntents as nearIntentsCfg} from \"./config.js\";\nimport {nearIntentsProvider, type NearIntentsProviderConfig} from \"./provider.js\";\n\nexport interface NearIntentsSwap2Config extends Swap2EngineConfig, NearIntentsProviderConfig {}\n\nexport class NearIntentsSwap2Protocol extends SingleProviderSwap2 {\n protected readonly provider;\n constructor(account: Swap2Account | undefined, config: NearIntentsSwap2Config) {\n super(account, config);\n this.provider = nearIntentsProvider(config);\n }\n protected override chainSupported(caip2: string): boolean {\n return nearIntentsCfg.supports(caip2, \"eip155:1\") || nearIntentsCfg.supports(\"eip155:1\", caip2);\n }\n protected override pairSupported(fromChain: string, toChain: string): boolean {\n return nearIntentsCfg.supports(fromChain, toChain);\n }\n}\n"],"mappings":"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","names":["import_util","import_swap2_assets"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { NearIntentsSuspendedChains, nearIntents, nearIntentsChainRefusal } from './config.cjs';
|
|
2
2
|
export { NearIntentsProviderConfig, nearIntentsProvider } from './provider.cjs';
|
|
3
|
-
export { NearIntentsSwap2Protocol, NearIntentsSwap2Protocol as default } from './protocol.cjs';
|
|
3
|
+
export { NearIntentsSwap2Config, NearIntentsSwap2Protocol, NearIntentsSwap2Protocol as default } from './protocol.cjs';
|
|
4
4
|
export { NEAR_INTENTS_CONTRACT, NEAR_INTENTS_MODULE, describeNearIntentsActivity } from './activity.cjs';
|
|
5
5
|
import '@anywalletkit/protocol-swap2-core/types';
|
|
6
6
|
import '@anywalletkit/protocol-swap2-core/swap2/single';
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { NearIntentsSuspendedChains, nearIntents, nearIntentsChainRefusal } from './config.js';
|
|
2
2
|
export { NearIntentsProviderConfig, nearIntentsProvider } from './provider.js';
|
|
3
|
-
export { NearIntentsSwap2Protocol, NearIntentsSwap2Protocol as default } from './protocol.js';
|
|
3
|
+
export { NearIntentsSwap2Config, NearIntentsSwap2Protocol, NearIntentsSwap2Protocol as default } from './protocol.js';
|
|
4
4
|
export { NEAR_INTENTS_CONTRACT, NEAR_INTENTS_MODULE, describeNearIntentsActivity } from './activity.js';
|
|
5
5
|
import '@anywalletkit/protocol-swap2-core/types';
|
|
6
6
|
import '@anywalletkit/protocol-swap2-core/swap2/single';
|
package/dist/index.js
CHANGED
package/dist/protocol.cjs
CHANGED
|
@@ -310,6 +310,7 @@ function nearIntentsProvider(config = {}) {
|
|
|
310
310
|
const s = await res.json();
|
|
311
311
|
const map = {
|
|
312
312
|
PENDING_DEPOSIT: "pending",
|
|
313
|
+
KNOWN_DEPOSIT_TX: "pending",
|
|
313
314
|
INCOMPLETE_DEPOSIT: "pending",
|
|
314
315
|
PROCESSING: "pending",
|
|
315
316
|
SUCCESS: "completed",
|
|
@@ -317,7 +318,7 @@ function nearIntentsProvider(config = {}) {
|
|
|
317
318
|
REFUNDED: "refunded"
|
|
318
319
|
};
|
|
319
320
|
const state = map[s.status ?? "PENDING_DEPOSIT"] ?? "pending";
|
|
320
|
-
const depositReceived = s.status === "PROCESSING" || s.status === "INCOMPLETE_DEPOSIT";
|
|
321
|
+
const depositReceived = s.status === "KNOWN_DEPOSIT_TX" || s.status === "PROCESSING" || s.status === "INCOMPLETE_DEPOSIT";
|
|
321
322
|
const destTx = txHashOf(s.swapDetails?.destinationChainTxHashes?.[0]);
|
|
322
323
|
return { state, depositReceived, ...destTx ? { destTxHash: destTx } : {} };
|
|
323
324
|
} catch {
|
package/dist/protocol.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/protocol.ts","../src/config.ts","../src/activity.ts","../src/provider.ts"],"sourcesContent":["import {SingleProviderSwap2} from \"@anywalletkit/protocol-swap2-core/swap2/single\";\nimport type {Swap2Account, Swap2EngineConfig} from \"@anywalletkit/protocol-swap2-core/swap2/base\";\nimport {nearIntents as nearIntentsCfg} from \"./config.js\";\nimport {nearIntentsProvider, type NearIntentsProviderConfig} from \"./provider.js\";\n\nexport interface NearIntentsSwap2Config extends Swap2EngineConfig, NearIntentsProviderConfig {}\n\nexport class NearIntentsSwap2Protocol extends SingleProviderSwap2 {\n protected readonly provider;\n constructor(account: Swap2Account | undefined, config: NearIntentsSwap2Config) {\n super(account, config);\n this.provider = nearIntentsProvider(config);\n }\n protected override chainSupported(caip2: string): boolean {\n return nearIntentsCfg.supports(caip2, \"eip155:1\") || nearIntentsCfg.supports(\"eip155:1\", caip2);\n }\n protected override pairSupported(fromChain: string, toChain: string): boolean {\n return nearIntentsCfg.supports(fromChain, toChain);\n }\n}\n","import {namespace} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {ccChain} from \"@anywalletkit/swap2-assets\";\n\n// ── NEAR Intents (1Click) — core, broadest coverage ─────────────────────────\nconst NEAR_INTENTS_NS = new Set([\n \"eip155\", \"solana\", \"tron\", \"bitcoin\", \"near\", \"sui\", \"ton\", \"zcash\",\n \"litecoin\", \"doge\", \"xrp\", \"bch\", \"cardano\", \"stellar\", \"aptos\",\n]);\n\n/**\n * Corridors the APP has paused (caip2 → why), passed in through the provider\n * config: a venue-side degradation (1Click's HOT omni-bridge assets answering\n * \"not available\" for days) is an operational switch, not SDK knowledge — the\n * wallet flips an env var and lifts it the same way when the venue recovers.\n */\nexport type NearIntentsSuspendedChains = Readonly<Record<string, string>>;\n\n/** Why a chain is refused up front, or null when 1Click can serve it. */\nexport function nearIntentsChainRefusal(chain: string, suspended: NearIntentsSuspendedChains = {}): string | null {\n if (!NEAR_INTENTS_NS.has(namespace(chain))) return `1Click does not serve ${chain}`;\n const why = suspended[chain];\n if (why) return `1Click corridor paused by the app: ${chain} — ${why}`;\n // A chain the catalog knows but carries no 1Click asset id for (World Chain,\n // Sei, Ink, Plume, X Layer, Unichain, MegaETH, Linea, Sonic, …) is LI.FI /\n // CCTP territory: the eip155 namespace alone used to claim it, and every\n // quote then died as \"unknown asset\" (2026-10-16 funded run).\n const listed = ccChain(chain)?.assets.some((a) => a.assetId.length > 0) ?? false;\n return listed ? null : `1Click does not list ${chain}`;\n}\n\nexport const nearIntents = {\n enabled: () => true,\n // Routes between any pair of 1Click-listed chains. 1Click is a NEAR-intents\n // solver network — it settles non-EVM↔non-EVM directly (BTC→Solana, Tron→\n // Base …), so this pre-filter must NOT require an EVM leg (the old \"vault\n // leg is always EVM\" assumption of the off-ramp flow silently blocked those\n // swap routes). A chain counts as listed when the shared catalog carries at\n // least one 1Click asset id for it and it is not suspended above; `getQuote`\n // is the real per-pair check and fail-closes (returns null, naming why) for\n // any pair 1Click can't actually route.\n // 2026-08 sweep: 1Click added LTC/DOGE/XRP/BCH/ADA/XLM/APT (+ the EVM\n // additions Avalanche/Scroll/Berachain, covered by the catalog ids).\n supportsChain(chain: string): boolean {\n return nearIntentsChainRefusal(chain) === null;\n },\n supports(from: string, to: string): boolean {\n return this.supportsChain(from) && this.supportsChain(to);\n },\n};\n","/**\n * Activity recognition for NEAR Intents (1Click).\n *\n * The source leg on EVM / TON / Solana / Tron / BTC is a plain transfer to a\n * one-time 1Click deposit address, and the destination leg is a plain transfer\n * from a solver / bridge account that changes per swap — neither carries a\n * stable on-chain marker, so they are NOT recognizable offline. The kit's\n * intent journal (the `intentId` returned by `swap2()`) ties those legs back to\n * the swap; this hook only answers for the legs that do have a fixed\n * counterparty: on NEAR itself, deposits into and withdrawals out of the\n * `intents.near` verifier contract (NEP-141 `ft_transfer_call` / `ft_withdraw`).\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {describeSwapLike} from \"@anywalletkit/protocol-swap2-core/activity\";\n\nexport const NEAR_INTENTS_MODULE = \"@anywalletkit/protocol-swap2-near-intents\";\n\n/** The NEAR Intents verifier / settlement contract. */\nexport const NEAR_INTENTS_CONTRACT = \"intents.near\";\n\nexport function describeNearIntentsActivity(tx: ChainTx, ctx: DescribeActivityContext): ActivityItem | null {\n if (!tx.chain.startsWith(\"near:\")) return null;\n const isOwn = (a: string) => ctx.own.has(a);\n const touches = tx.transfers.some((t) => (t.from === NEAR_INTENTS_CONTRACT && isOwn(t.to)) || (t.to === NEAR_INTENTS_CONTRACT && isOwn(t.from)));\n if (!touches) return null;\n return describeSwapLike(tx, ctx, {\n protocol: NEAR_INTENTS_MODULE,\n subtitle: \"NEAR Intents\",\n kind: \"bridge\",\n counterparty: NEAR_INTENTS_CONTRACT,\n inSuffix: \"via NEAR Intents\",\n });\n}\n","import {nearIntents as cfg, nearIntentsChainRefusal, type NearIntentsSuspendedChains} from \"./config.js\";\nimport {describeNearIntentsActivity} from \"./activity.js\";\nimport {timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {CC_DEST, ccAsset, ccAssetByToken, ccChain} from \"@anywalletkit/swap2-assets\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * NEAR Intents (1Click) provider — the core route, broadest coverage. Ported\n * from a production 1Click integration:\n * dry quote → pricing preview; live quote → depositAddress the user funds\n * from any wallet; status polled by depositAddress.\n * Runs server-side, so the partner JWT stays here (no proxy needed). Defensive:\n * any API error yields a null quote so the provider drops out of that round.\n */\n\nconst ONE_CLICK_DEFAULT = \"https://1click.chaindefuser.com/v0\";\nconst QUOTE_TTL_MS = 55_000;\n\n/** intentId durably carries both status lookup keys (memo is quote-specific). */\nconst INTENT_PREFIX = \"near1click:\";\n\nfunction encodeIntent(depositAddress: string, depositMemo: string | null): string {\n return `${INTENT_PREFIX}${encodeURIComponent(depositAddress)}|${encodeURIComponent(depositMemo ?? \"\")}`;\n}\n\nfunction decodeIntent(intentId: string): {depositAddress: string; depositMemo?: string} {\n try {\n if (!intentId.startsWith(INTENT_PREFIX)) throw new Error(\"unsupported id version\");\n const raw = intentId.slice(INTENT_PREFIX.length);\n const parts = raw.split(\"|\");\n if (parts.length !== 2 || !parts[0]) throw new Error(\"invalid id shape\");\n const depositAddress = decodeURIComponent(parts[0]);\n const memo = decodeURIComponent(parts[1] ?? \"\");\n if (!depositAddress) throw new Error(\"empty deposit address\");\n return {depositAddress, ...(memo ? {depositMemo: memo} : {})};\n } catch {\n throw new Error(\"near-intents: malformed intent id\");\n }\n}\n\nfunction authHeaders(jwtOverride?: string): Record<string, string> {\n const h: Record<string, string> = {\"content-type\": \"application/json\", accept: \"application/json\"};\n const jwt = jwtOverride;\n if (jwt) h.authorization = `Bearer ${jwt}`;\n return h;\n}\n\n/** Our integrator fee, injected server-side when a recipient is configured. */\nfunction appFees(recipient?: string, bps?: number): {recipient: string; fee: number}[] | undefined {\n return recipient !== undefined && bps !== undefined ? [{recipient, fee: bps}] : undefined;\n}\n\n/**\n * Per-source deposit + refund config. Every live default keeps failed-swap\n * ownership on the caller's source-chain address.\n */\nfunction depositConfig(_sourceChain: string, refundAddress: string, _dry: boolean) {\n // Every source refunds to the caller's own source-chain address (Zcash\n // included — a t-address placeholder serves dry quotes since 2026-10-18).\n // Never redirect failed swaps to an integrator-owned NEAR account.\n return {depositType: \"ORIGIN_CHAIN\", refundType: \"ORIGIN_CHAIN\", refundTo: refundAddress};\n}\n\n/** Placeholder sender/recipient for dry quotes (1Click requires the fields). */\nconst PLACEHOLDER: Record<string, string> = {\n bitcoin: \"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq\",\n ton: \"UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ\",\n // NOT a token mint: with the USDC mint here, every dry quote whose ORIGIN\n // was Solana USDC answered 500 \"Internal server error\" (2026-10-09) — a\n // refund \"to the asset's own mint\" trips 1Click. The incinerator is a\n // plain, valid system address.\n solana: \"1nc1nerator11111111111111111111111111111111\",\n tron: \"TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9\",\n // NEAR refunds go to an account id; the registrar account always exists.\n near: \"near\",\n // A live transparent address (exchange hot wallet); dry quotes only.\n zcash: \"t1KfwsnwJeNRVjQGBDZhwKskpQbih2qx5Ua\",\n eip155: \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",\n};\n\nfunction placeholderFor(chain: string): string {\n return PLACEHOLDER[chain.split(\":\")[0] ?? \"\"] ?? PLACEHOLDER.eip155!;\n}\n\nfunction deadlineIn(minutes: number): string {\n return new Date(Date.now() + minutes * 60_000).toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n}\n\n/**\n * dest asset id for ANY chain in the catalog (inbound → Ethereum, or the step-2\n * off-ramp → any supported chain). Falls back to the Ethereum omft pattern for\n * a mainnet ERC-20 that isn't in the curated catalog.\n */\nfunction destAssetId(destChain: string, destToken: string): string | null {\n const asset = ccAssetByToken(destChain, destToken);\n if (asset) return asset.assetId;\n if (destChain === CC_DEST.caip2 && /^0x[0-9a-fA-F]{40}$/.test(destToken)) {\n return `nep141:eth-${destToken.toLowerCase()}.omft.near`;\n }\n return null;\n}\n\ntype OneClickQuote = {\n quote?: Record<string, unknown>;\n correlationId?: string;\n error?: string;\n message?: string;\n};\n\n/** 1Click returns tx hashes either as strings or {hash, explorerUrl}. */\nfunction txHashOf(entry: unknown): string | null {\n if (!entry) return null;\n if (typeof entry === \"string\") return entry;\n const h = (entry as {hash?: string}).hash;\n return typeof h === \"string\" ? h : null;\n}\n\n/** Explicit constructor configuration; no deployment environment is read. */\nexport interface NearIntentsProviderConfig {\n enabled?: boolean;\n apiUrl?: string;\n jwt?: string;\n feeRecipient?: string;\n feeBps?: number;\n /** Corridors the app has paused (caip2 → reason): refused up front, by name, until the app lifts them. */\n suspendedChains?: NearIntentsSuspendedChains;\n}\n\nexport function nearIntentsProvider(config: NearIntentsProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const parsedApiUrl = new URL(config.apiUrl ?? ONE_CLICK_DEFAULT);\n if (parsedApiUrl.protocol !== \"https:\" && parsedApiUrl.protocol !== \"http:\") {\n throw new Error(\"near-intents: apiUrl must use http or https\");\n }\n const apiBase = parsedApiUrl.toString().replace(/\\/$/, \"\");\n const hasRecipient = config.feeRecipient !== undefined;\n const hasBps = config.feeBps !== undefined;\n if (hasRecipient !== hasBps) throw new Error(\"near-intents: feeRecipient and feeBps must be configured together\");\n if (hasRecipient && (!config.feeRecipient!.trim() || !Number.isInteger(config.feeBps) || config.feeBps! <= 0 || config.feeBps! > 10_000)) {\n throw new Error(\"near-intents: fee config requires a recipient and feeBps between 1 and 10000\");\n }\n return {\n name: \"near_intents\",\n describeActivity: describeNearIntentsActivity,\n enabled: () => config.enabled ?? true,\n\n // Capability discovery comes from the provider itself, so it can run alone\n // or inside the optional aggregator without a central capability table.\n supportsChain: (chain: string) => cfg.supportsChain(chain),\n supportsChainPair: (fromChain: string, toChain: string) => cfg.supports(fromChain, toChain),\n supportsRoute(from: Asset, to: Asset): boolean {\n // Chain-level gate first (namespace, catalog listing, hand-suspended\n // corridors such as TON while the HOT bridge is dark) …\n if (!cfg.supports(from.chain, to.chain)) return false;\n // … then only pairs present in the curated catalog are offered — and only\n // those with a 1Click asset id (LI.FI-only tokens carry an empty assetId).\n // Both ends: a destination 1Click doesn't list (Unichain, MegaETH, …)\n // answered \"unknown asset\" on every quote (589 of the 2026-10-10 matrix).\n const asset = ccAsset(from.chain, from.token);\n return !!ccChain(from.chain) && !!asset?.assetId && !!destAssetId(to.chain, to.token);\n },\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n // Every refusal below names itself: on the server these lines are the\n // only visibility into WHY a live quote returned null (the wire answer\n // is just `null`), and \"no route\" bugs hide in exactly that silence.\n const refuse = (reason: string): null => {\n const detail = `${reason} [dry=${params.dry !== false} ${params.sourceChain}->${params.destChain} amount=${params.amountIn}]`;\n // Caller fields and 1Click text are untrusted: no control characters in server logs.\n console.warn(`near-intents: no quote — ${detail.replace(/[\\u0000-\\u001f\\u007f]/g, \" \")}`);\n params.onRefusal?.(detail);\n return null;\n };\n // Up-front, named refusals — no wire call for a corridor 1Click cannot\n // serve: a chain outside its list / suspended by hand, or a token the\n // catalog carries without a 1Click asset id (\"1Click does not list …\").\n const paused = config.suspendedChains ?? {};\n const chainRefusal = nearIntentsChainRefusal(params.sourceChain, paused) ?? nearIntentsChainRefusal(params.destChain, paused);\n if (chainRefusal) return refuse(chainRefusal);\n const origin = ccAsset(params.sourceChain, params.sourceToken);\n if (!origin?.assetId) return refuse(`1Click does not list ${params.sourceChain} ${params.sourceToken}`);\n const destination = destAssetId(params.destChain, params.destToken);\n if (!destination) return refuse(`1Click does not list ${params.destChain} ${params.destToken}`);\n const dry = params.dry !== false;\n // A live quote derives the deposit address from the refund config —\n // never create one without a real refund destination.\n const refund = params.refundAddress ?? (dry ? placeholderFor(params.sourceChain) : \"\");\n const dcfg = depositConfig(params.sourceChain, refund, dry);\n if (!dry && !dcfg.refundTo) return refuse(\"live quote without a refund address\");\n\n const requestedDeadline = deadlineIn(60);\n const body: Record<string, unknown> = {\n dry,\n // FLEX_INPUT (exchange flow): the address accepts any amount; amountIn\n // is just the pricing notional. Verified against the live API.\n swapType: params.flex ? \"FLEX_INPUT\" : \"EXACT_INPUT\",\n slippageTolerance: params.slippageBps ?? 100,\n originAsset: origin.assetId,\n depositType: dcfg.depositType,\n destinationAsset: destination,\n amount: params.amountIn,\n refundTo: dcfg.refundTo,\n refundType: dcfg.refundType,\n recipient: params.destAddress,\n recipientType: \"DESTINATION_CHAIN\",\n deadline: requestedDeadline,\n };\n const fees = appFees(config.feeRecipient, config.feeBps);\n if (fees) body.appFees = fees;\n\n try {\n // 1Click's solver auction flaps: the same body can answer 400 \"No\n // liquidity available\" and 201 seconds apart (observed live on\n // TON USDT -> ETH). A transient flap on the EXECUTION quote would\n // surface as a terminal \"no route\" right after a successful display\n // quote, so ride through it: up to two retries on liquidity flaps,\n // 5xx and network errors. Real rejections (bad address, unknown\n // asset) still fail on the first answer.\n let res: Response | null = null;\n let data: OneClickQuote = {};\n for (let attempt = 0; ; attempt++) {\n try {\n res = await fetch(`${apiBase}/quote`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify(body),\n signal: signal ?? timeoutSignal(12_000),\n });\n data = (await res.json().catch(() => ({}))) as OneClickQuote;\n } catch (err) {\n if (attempt >= 2 || signal?.aborted) throw err;\n res = null;\n }\n if (res?.ok) break;\n const flaky =\n res === null ||\n res.status >= 500 ||\n (res.status === 400 && /no liquidity/i.test(String(data.message ?? \"\")));\n if (!flaky || attempt >= 2 || signal?.aborted) break;\n await new Promise((resolve) => setTimeout(resolve, 500 * (attempt + 1)));\n }\n if (!res?.ok) return refuse(`1Click ${res?.status ?? \"network error\"}: ${String(data.message ?? \"\").slice(0, 200)}`);\n const q = (data.quote ?? {}) as Record<string, unknown>;\n\n const depositAddress = typeof q.depositAddress === \"string\" ? q.depositAddress : \"\";\n if (!dry && !depositAddress) return refuse(\"live quote came back without a deposit address\");\n const inUsd = Number.parseFloat(String(q.amountInUsd ?? \"0\"));\n const outUsd = Number.parseFloat(String(q.amountOutUsd ?? \"0\"));\n const parsedDeadline = Date.parse(String(q.deadline ?? \"\"));\n if (!dry && (!Number.isFinite(parsedDeadline) || parsedDeadline <= Date.now())) return refuse(`unusable deadline ${String(q.deadline)}`);\n const deadline = Number.isFinite(parsedDeadline) && parsedDeadline > Date.now()\n ? Math.min(parsedDeadline, Date.now() + QUOTE_TTL_MS)\n : Date.now() + QUOTE_TTL_MS;\n\n if (q.amountIn !== undefined && String(q.amountIn) !== params.amountIn) return refuse(`amountIn mismatch (${String(q.amountIn)} vs ${params.amountIn})`);\n\n // amountOut is optimistic, not a guaranteed floor. Live execution must\n // not fabricate a minimum when the provider omits it.\n if (q.minAmountOut === undefined || q.minAmountOut === null) return refuse(\"quote has no minAmountOut\");\n const minDestAmount = String(q.minAmountOut);\n if (params.minAmountOut !== undefined && BigInt(minDestAmount) < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${minDestAmount} < floor=${params.minAmountOut})`);\n const depositMemo =\n (typeof q.depositMemo === \"string\" && q.depositMemo) ||\n (typeof q.memo === \"string\" && q.memo) ||\n null;\n return {\n provider: \"near_intents\",\n intentId: depositAddress ? encodeIntent(depositAddress, depositMemo) : `dry:${crypto.randomUUID()}`,\n depositAddress,\n depositMemo,\n sourceAmount: params.amountIn,\n destAmount: String(q.amountOut ?? \"0\"),\n minDestAmount,\n feeUsd: Math.max(0, inUsd - outUsd),\n etaSeconds: Number(q.timeEstimate ?? 60),\n reliability: 0.95,\n validUntilMs: deadline,\n };\n } catch (err) {\n return refuse(`threw: ${err instanceof Error ? err.message.slice(0, 200) : String(err).slice(0, 200)}`);\n }\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n return {\n chain: \"\",\n to: quote.depositAddress,\n value: quote.sourceAmount,\n ...(quote.depositMemo ? {memo: quote.depositMemo} : {}),\n };\n },\n\n async notifyDeposit(intentId: string, txHash: string): Promise<void> {\n const {depositAddress} = decodeIntent(intentId);\n const res = await fetch(`${apiBase}/deposit/submit`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify({depositAddress, txHash}),\n signal: timeoutSignal(12_000),\n });\n if (!res.ok) throw new Error(`near-intents: deposit notification failed (${res.status})`);\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n const {depositAddress, depositMemo} = decodeIntent(ref.intentId);\n // Durable retry: BaseSwap2Protocol embeds the source hash in the swap2\n // id. If the post-broadcast notify failed, every status poll retries it.\n if (ref.sourceTxHash) {\n await this.notifyDeposit?.(ref.intentId, ref.sourceTxHash).catch(() => {});\n }\n try {\n const query = new URLSearchParams({depositAddress});\n if (depositMemo) query.set(\"depositMemo\", depositMemo);\n const res = await fetch(\n `${apiBase}/status?${query.toString()}`,\n {headers: authHeaders(config.jwt), signal: timeoutSignal(12_000)},\n );\n if (!res.ok) return {state: \"pending\"};\n const s = (await res.json()) as {\n status?: string;\n swapDetails?: {destinationChainTxHashes?: unknown[]};\n };\n const map: Record<string, IntentStatus[\"state\"]> = {\n PENDING_DEPOSIT: \"pending\",\n INCOMPLETE_DEPOSIT: \"pending\",\n PROCESSING: \"pending\",\n SUCCESS: \"completed\",\n FAILED: \"failed\",\n REFUNDED: \"refunded\",\n };\n const state = map[s.status ?? \"PENDING_DEPOSIT\"] ?? \"pending\";\n const depositReceived = s.status === \"PROCESSING\" || s.status === \"INCOMPLETE_DEPOSIT\";\n const destTx = txHashOf(s.swapDetails?.destinationChainTxHashes?.[0]);\n return {state, depositReceived, ...(destTx ? {destTxHash: destTx} : {})};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n"],"mappings":"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","names":["import_util","import_swap2_assets"]}
|
|
1
|
+
{"version":3,"sources":["../src/protocol.ts","../src/config.ts","../src/activity.ts","../src/provider.ts"],"sourcesContent":["import {SingleProviderSwap2} from \"@anywalletkit/protocol-swap2-core/swap2/single\";\nimport type {Swap2Account, Swap2EngineConfig} from \"@anywalletkit/protocol-swap2-core/swap2/base\";\nimport {nearIntents as nearIntentsCfg} from \"./config.js\";\nimport {nearIntentsProvider, type NearIntentsProviderConfig} from \"./provider.js\";\n\nexport interface NearIntentsSwap2Config extends Swap2EngineConfig, NearIntentsProviderConfig {}\n\nexport class NearIntentsSwap2Protocol extends SingleProviderSwap2 {\n protected readonly provider;\n constructor(account: Swap2Account | undefined, config: NearIntentsSwap2Config) {\n super(account, config);\n this.provider = nearIntentsProvider(config);\n }\n protected override chainSupported(caip2: string): boolean {\n return nearIntentsCfg.supports(caip2, \"eip155:1\") || nearIntentsCfg.supports(\"eip155:1\", caip2);\n }\n protected override pairSupported(fromChain: string, toChain: string): boolean {\n return nearIntentsCfg.supports(fromChain, toChain);\n }\n}\n","import {namespace} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {ccChain} from \"@anywalletkit/swap2-assets\";\n\n// ── NEAR Intents (1Click) — core, broadest coverage ─────────────────────────\nconst NEAR_INTENTS_NS = new Set([\n \"eip155\", \"solana\", \"tron\", \"bitcoin\", \"near\", \"sui\", \"ton\", \"zcash\",\n \"litecoin\", \"doge\", \"xrp\", \"bch\", \"cardano\", \"stellar\", \"aptos\",\n]);\n\n/**\n * Corridors the APP has paused (caip2 → why), passed in through the provider\n * config: a venue-side degradation (1Click's HOT omni-bridge assets answering\n * \"not available\" for days) is an operational switch, not SDK knowledge — the\n * wallet flips an env var and lifts it the same way when the venue recovers.\n */\nexport type NearIntentsSuspendedChains = Readonly<Record<string, string>>;\n\n/** Why a chain is refused up front, or null when 1Click can serve it. */\nexport function nearIntentsChainRefusal(chain: string, suspended: NearIntentsSuspendedChains = {}): string | null {\n if (!NEAR_INTENTS_NS.has(namespace(chain))) return `1Click does not serve ${chain}`;\n const why = suspended[chain];\n if (why) return `1Click corridor paused by the app: ${chain} — ${why}`;\n // A chain the catalog knows but carries no 1Click asset id for (World Chain,\n // Sei, Ink, Plume, X Layer, Unichain, MegaETH, Linea, Sonic, …) is LI.FI /\n // CCTP territory: the eip155 namespace alone used to claim it, and every\n // quote then died as \"unknown asset\" (2026-10-16 funded run).\n const listed = ccChain(chain)?.assets.some((a) => a.assetId.length > 0) ?? false;\n return listed ? null : `1Click does not list ${chain}`;\n}\n\nexport const nearIntents = {\n enabled: () => true,\n // Routes between any pair of 1Click-listed chains. 1Click is a NEAR-intents\n // solver network — it settles non-EVM↔non-EVM directly (BTC→Solana, Tron→\n // Base …), so this pre-filter must NOT require an EVM leg (the old \"vault\n // leg is always EVM\" assumption of the off-ramp flow silently blocked those\n // swap routes). A chain counts as listed when the shared catalog carries at\n // least one 1Click asset id for it and it is not suspended above; `getQuote`\n // is the real per-pair check and fail-closes (returns null, naming why) for\n // any pair 1Click can't actually route.\n // 2026-08 sweep: 1Click added LTC/DOGE/XRP/BCH/ADA/XLM/APT (+ the EVM\n // additions Avalanche/Scroll/Berachain, covered by the catalog ids).\n supportsChain(chain: string): boolean {\n return nearIntentsChainRefusal(chain) === null;\n },\n supports(from: string, to: string): boolean {\n return this.supportsChain(from) && this.supportsChain(to);\n },\n};\n","/**\n * Activity recognition for NEAR Intents (1Click).\n *\n * The source leg on EVM / TON / Solana / Tron / BTC is a plain transfer to a\n * one-time 1Click deposit address, and the destination leg is a plain transfer\n * from a solver / bridge account that changes per swap — neither carries a\n * stable on-chain marker, so they are NOT recognizable offline. The kit's\n * intent journal (the `intentId` returned by `swap2()`) ties those legs back to\n * the swap; this hook only answers for the legs that do have a fixed\n * counterparty: on NEAR itself, deposits into and withdrawals out of the\n * `intents.near` verifier contract (NEP-141 `ft_transfer_call` / `ft_withdraw`).\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {describeSwapLike} from \"@anywalletkit/protocol-swap2-core/activity\";\n\nexport const NEAR_INTENTS_MODULE = \"@anywalletkit/protocol-swap2-near-intents\";\n\n/** The NEAR Intents verifier / settlement contract. */\nexport const NEAR_INTENTS_CONTRACT = \"intents.near\";\n\nexport function describeNearIntentsActivity(tx: ChainTx, ctx: DescribeActivityContext): ActivityItem | null {\n if (!tx.chain.startsWith(\"near:\")) return null;\n const isOwn = (a: string) => ctx.own.has(a);\n const touches = tx.transfers.some((t) => (t.from === NEAR_INTENTS_CONTRACT && isOwn(t.to)) || (t.to === NEAR_INTENTS_CONTRACT && isOwn(t.from)));\n if (!touches) return null;\n return describeSwapLike(tx, ctx, {\n protocol: NEAR_INTENTS_MODULE,\n subtitle: \"NEAR Intents\",\n kind: \"bridge\",\n counterparty: NEAR_INTENTS_CONTRACT,\n inSuffix: \"via NEAR Intents\",\n });\n}\n","import {nearIntents as cfg, nearIntentsChainRefusal, type NearIntentsSuspendedChains} from \"./config.js\";\nimport {describeNearIntentsActivity} from \"./activity.js\";\nimport {timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {CC_DEST, ccAsset, ccAssetByToken, ccChain} from \"@anywalletkit/swap2-assets\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * NEAR Intents (1Click) provider — the core route, broadest coverage. Ported\n * from a production 1Click integration:\n * dry quote → pricing preview; live quote → depositAddress the user funds\n * from any wallet; status polled by depositAddress.\n * Runs server-side, so the partner JWT stays here (no proxy needed). Defensive:\n * any API error yields a null quote so the provider drops out of that round.\n */\n\nconst ONE_CLICK_DEFAULT = \"https://1click.chaindefuser.com/v0\";\nconst QUOTE_TTL_MS = 55_000;\n\n/** intentId durably carries both status lookup keys (memo is quote-specific). */\nconst INTENT_PREFIX = \"near1click:\";\n\nfunction encodeIntent(depositAddress: string, depositMemo: string | null): string {\n return `${INTENT_PREFIX}${encodeURIComponent(depositAddress)}|${encodeURIComponent(depositMemo ?? \"\")}`;\n}\n\nfunction decodeIntent(intentId: string): {depositAddress: string; depositMemo?: string} {\n try {\n if (!intentId.startsWith(INTENT_PREFIX)) throw new Error(\"unsupported id version\");\n const raw = intentId.slice(INTENT_PREFIX.length);\n const parts = raw.split(\"|\");\n if (parts.length !== 2 || !parts[0]) throw new Error(\"invalid id shape\");\n const depositAddress = decodeURIComponent(parts[0]);\n const memo = decodeURIComponent(parts[1] ?? \"\");\n if (!depositAddress) throw new Error(\"empty deposit address\");\n return {depositAddress, ...(memo ? {depositMemo: memo} : {})};\n } catch {\n throw new Error(\"near-intents: malformed intent id\");\n }\n}\n\nfunction authHeaders(jwtOverride?: string): Record<string, string> {\n const h: Record<string, string> = {\"content-type\": \"application/json\", accept: \"application/json\"};\n const jwt = jwtOverride;\n if (jwt) h.authorization = `Bearer ${jwt}`;\n return h;\n}\n\n/** Our integrator fee, injected server-side when a recipient is configured. */\nfunction appFees(recipient?: string, bps?: number): {recipient: string; fee: number}[] | undefined {\n return recipient !== undefined && bps !== undefined ? [{recipient, fee: bps}] : undefined;\n}\n\n/**\n * Per-source deposit + refund config. Every live default keeps failed-swap\n * ownership on the caller's source-chain address.\n */\nfunction depositConfig(_sourceChain: string, refundAddress: string, _dry: boolean) {\n // Every source refunds to the caller's own source-chain address (Zcash\n // included — a t-address placeholder serves dry quotes since 2026-10-18).\n // Never redirect failed swaps to an integrator-owned NEAR account.\n return {depositType: \"ORIGIN_CHAIN\", refundType: \"ORIGIN_CHAIN\", refundTo: refundAddress};\n}\n\n/** Placeholder sender/recipient for dry quotes (1Click requires the fields). */\nconst PLACEHOLDER: Record<string, string> = {\n bitcoin: \"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq\",\n ton: \"UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ\",\n // NOT a token mint: with the USDC mint here, every dry quote whose ORIGIN\n // was Solana USDC answered 500 \"Internal server error\" (2026-10-09) — a\n // refund \"to the asset's own mint\" trips 1Click. The incinerator is a\n // plain, valid system address.\n solana: \"1nc1nerator11111111111111111111111111111111\",\n tron: \"TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9\",\n // NEAR refunds go to an account id; the registrar account always exists.\n near: \"near\",\n // A live transparent address (exchange hot wallet); dry quotes only.\n zcash: \"t1KfwsnwJeNRVjQGBDZhwKskpQbih2qx5Ua\",\n eip155: \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",\n};\n\nfunction placeholderFor(chain: string): string {\n return PLACEHOLDER[chain.split(\":\")[0] ?? \"\"] ?? PLACEHOLDER.eip155!;\n}\n\nfunction deadlineIn(minutes: number): string {\n return new Date(Date.now() + minutes * 60_000).toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n}\n\n/**\n * dest asset id for ANY chain in the catalog (inbound → Ethereum, or the step-2\n * off-ramp → any supported chain). Falls back to the Ethereum omft pattern for\n * a mainnet ERC-20 that isn't in the curated catalog.\n */\nfunction destAssetId(destChain: string, destToken: string): string | null {\n const asset = ccAssetByToken(destChain, destToken);\n if (asset) return asset.assetId;\n if (destChain === CC_DEST.caip2 && /^0x[0-9a-fA-F]{40}$/.test(destToken)) {\n return `nep141:eth-${destToken.toLowerCase()}.omft.near`;\n }\n return null;\n}\n\ntype OneClickQuote = {\n quote?: Record<string, unknown>;\n correlationId?: string;\n error?: string;\n message?: string;\n};\n\n/** 1Click returns tx hashes either as strings or {hash, explorerUrl}. */\nfunction txHashOf(entry: unknown): string | null {\n if (!entry) return null;\n if (typeof entry === \"string\") return entry;\n const h = (entry as {hash?: string}).hash;\n return typeof h === \"string\" ? h : null;\n}\n\n/** Explicit constructor configuration; no deployment environment is read. */\nexport interface NearIntentsProviderConfig {\n enabled?: boolean;\n apiUrl?: string;\n jwt?: string;\n feeRecipient?: string;\n feeBps?: number;\n /** Corridors the app has paused (caip2 → reason): refused up front, by name, until the app lifts them. */\n suspendedChains?: NearIntentsSuspendedChains;\n}\n\nexport function nearIntentsProvider(config: NearIntentsProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const parsedApiUrl = new URL(config.apiUrl ?? ONE_CLICK_DEFAULT);\n if (parsedApiUrl.protocol !== \"https:\" && parsedApiUrl.protocol !== \"http:\") {\n throw new Error(\"near-intents: apiUrl must use http or https\");\n }\n const apiBase = parsedApiUrl.toString().replace(/\\/$/, \"\");\n const hasRecipient = config.feeRecipient !== undefined;\n const hasBps = config.feeBps !== undefined;\n if (hasRecipient !== hasBps) throw new Error(\"near-intents: feeRecipient and feeBps must be configured together\");\n if (hasRecipient && (!config.feeRecipient!.trim() || !Number.isInteger(config.feeBps) || config.feeBps! <= 0 || config.feeBps! > 10_000)) {\n throw new Error(\"near-intents: fee config requires a recipient and feeBps between 1 and 10000\");\n }\n return {\n name: \"near_intents\",\n describeActivity: describeNearIntentsActivity,\n enabled: () => config.enabled ?? true,\n\n // Capability discovery comes from the provider itself, so it can run alone\n // or inside the optional aggregator without a central capability table.\n supportsChain: (chain: string) => cfg.supportsChain(chain),\n supportsChainPair: (fromChain: string, toChain: string) => cfg.supports(fromChain, toChain),\n supportsRoute(from: Asset, to: Asset): boolean {\n // Chain-level gate first (namespace, catalog listing, hand-suspended\n // corridors such as TON while the HOT bridge is dark) …\n if (!cfg.supports(from.chain, to.chain)) return false;\n // … then only pairs present in the curated catalog are offered — and only\n // those with a 1Click asset id (LI.FI-only tokens carry an empty assetId).\n // Both ends: a destination 1Click doesn't list (Unichain, MegaETH, …)\n // answered \"unknown asset\" on every quote (589 of the 2026-10-10 matrix).\n const asset = ccAsset(from.chain, from.token);\n return !!ccChain(from.chain) && !!asset?.assetId && !!destAssetId(to.chain, to.token);\n },\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n // Every refusal below names itself: on the server these lines are the\n // only visibility into WHY a live quote returned null (the wire answer\n // is just `null`), and \"no route\" bugs hide in exactly that silence.\n const refuse = (reason: string): null => {\n const detail = `${reason} [dry=${params.dry !== false} ${params.sourceChain}->${params.destChain} amount=${params.amountIn}]`;\n // Caller fields and 1Click text are untrusted: no control characters in server logs.\n console.warn(`near-intents: no quote — ${detail.replace(/[\\u0000-\\u001f\\u007f]/g, \" \")}`);\n params.onRefusal?.(detail);\n return null;\n };\n // Up-front, named refusals — no wire call for a corridor 1Click cannot\n // serve: a chain outside its list / suspended by hand, or a token the\n // catalog carries without a 1Click asset id (\"1Click does not list …\").\n const paused = config.suspendedChains ?? {};\n const chainRefusal = nearIntentsChainRefusal(params.sourceChain, paused) ?? nearIntentsChainRefusal(params.destChain, paused);\n if (chainRefusal) return refuse(chainRefusal);\n const origin = ccAsset(params.sourceChain, params.sourceToken);\n if (!origin?.assetId) return refuse(`1Click does not list ${params.sourceChain} ${params.sourceToken}`);\n const destination = destAssetId(params.destChain, params.destToken);\n if (!destination) return refuse(`1Click does not list ${params.destChain} ${params.destToken}`);\n const dry = params.dry !== false;\n // A live quote derives the deposit address from the refund config —\n // never create one without a real refund destination.\n const refund = params.refundAddress ?? (dry ? placeholderFor(params.sourceChain) : \"\");\n const dcfg = depositConfig(params.sourceChain, refund, dry);\n if (!dry && !dcfg.refundTo) return refuse(\"live quote without a refund address\");\n\n const requestedDeadline = deadlineIn(60);\n const body: Record<string, unknown> = {\n dry,\n // FLEX_INPUT (exchange flow): the address accepts any amount; amountIn\n // is just the pricing notional. Verified against the live API.\n swapType: params.flex ? \"FLEX_INPUT\" : \"EXACT_INPUT\",\n slippageTolerance: params.slippageBps ?? 100,\n originAsset: origin.assetId,\n depositType: dcfg.depositType,\n destinationAsset: destination,\n amount: params.amountIn,\n refundTo: dcfg.refundTo,\n refundType: dcfg.refundType,\n recipient: params.destAddress,\n recipientType: \"DESTINATION_CHAIN\",\n deadline: requestedDeadline,\n };\n const fees = appFees(config.feeRecipient, config.feeBps);\n if (fees) body.appFees = fees;\n\n try {\n // 1Click's solver auction flaps: the same body can answer 400 \"No\n // liquidity available\" and 201 seconds apart (observed live on\n // TON USDT -> ETH). A transient flap on the EXECUTION quote would\n // surface as a terminal \"no route\" right after a successful display\n // quote, so ride through it: up to two retries on liquidity flaps,\n // 5xx and network errors. Real rejections (bad address, unknown\n // asset) still fail on the first answer.\n let res: Response | null = null;\n let data: OneClickQuote = {};\n for (let attempt = 0; ; attempt++) {\n try {\n res = await fetch(`${apiBase}/quote`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify(body),\n signal: signal ?? timeoutSignal(12_000),\n });\n data = (await res.json().catch(() => ({}))) as OneClickQuote;\n } catch (err) {\n if (attempt >= 2 || signal?.aborted) throw err;\n res = null;\n }\n if (res?.ok) break;\n const flaky =\n res === null ||\n res.status >= 500 ||\n (res.status === 400 && /no liquidity/i.test(String(data.message ?? \"\")));\n if (!flaky || attempt >= 2 || signal?.aborted) break;\n await new Promise((resolve) => setTimeout(resolve, 500 * (attempt + 1)));\n }\n if (!res?.ok) return refuse(`1Click ${res?.status ?? \"network error\"}: ${String(data.message ?? \"\").slice(0, 200)}`);\n const q = (data.quote ?? {}) as Record<string, unknown>;\n\n const depositAddress = typeof q.depositAddress === \"string\" ? q.depositAddress : \"\";\n if (!dry && !depositAddress) return refuse(\"live quote came back without a deposit address\");\n const inUsd = Number.parseFloat(String(q.amountInUsd ?? \"0\"));\n const outUsd = Number.parseFloat(String(q.amountOutUsd ?? \"0\"));\n const parsedDeadline = Date.parse(String(q.deadline ?? \"\"));\n if (!dry && (!Number.isFinite(parsedDeadline) || parsedDeadline <= Date.now())) return refuse(`unusable deadline ${String(q.deadline)}`);\n const deadline = Number.isFinite(parsedDeadline) && parsedDeadline > Date.now()\n ? Math.min(parsedDeadline, Date.now() + QUOTE_TTL_MS)\n : Date.now() + QUOTE_TTL_MS;\n\n if (q.amountIn !== undefined && String(q.amountIn) !== params.amountIn) return refuse(`amountIn mismatch (${String(q.amountIn)} vs ${params.amountIn})`);\n\n // amountOut is optimistic, not a guaranteed floor. Live execution must\n // not fabricate a minimum when the provider omits it.\n if (q.minAmountOut === undefined || q.minAmountOut === null) return refuse(\"quote has no minAmountOut\");\n const minDestAmount = String(q.minAmountOut);\n if (params.minAmountOut !== undefined && BigInt(minDestAmount) < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${minDestAmount} < floor=${params.minAmountOut})`);\n const depositMemo =\n (typeof q.depositMemo === \"string\" && q.depositMemo) ||\n (typeof q.memo === \"string\" && q.memo) ||\n null;\n return {\n provider: \"near_intents\",\n intentId: depositAddress ? encodeIntent(depositAddress, depositMemo) : `dry:${crypto.randomUUID()}`,\n depositAddress,\n depositMemo,\n sourceAmount: params.amountIn,\n destAmount: String(q.amountOut ?? \"0\"),\n minDestAmount,\n feeUsd: Math.max(0, inUsd - outUsd),\n etaSeconds: Number(q.timeEstimate ?? 60),\n reliability: 0.95,\n validUntilMs: deadline,\n };\n } catch (err) {\n return refuse(`threw: ${err instanceof Error ? err.message.slice(0, 200) : String(err).slice(0, 200)}`);\n }\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n return {\n chain: \"\",\n to: quote.depositAddress,\n value: quote.sourceAmount,\n ...(quote.depositMemo ? {memo: quote.depositMemo} : {}),\n };\n },\n\n async notifyDeposit(intentId: string, txHash: string): Promise<void> {\n const {depositAddress} = decodeIntent(intentId);\n const res = await fetch(`${apiBase}/deposit/submit`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify({depositAddress, txHash}),\n signal: timeoutSignal(12_000),\n });\n if (!res.ok) throw new Error(`near-intents: deposit notification failed (${res.status})`);\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n const {depositAddress, depositMemo} = decodeIntent(ref.intentId);\n // Durable retry: BaseSwap2Protocol embeds the source hash in the swap2\n // id. If the post-broadcast notify failed, every status poll retries it.\n if (ref.sourceTxHash) {\n await this.notifyDeposit?.(ref.intentId, ref.sourceTxHash).catch(() => {});\n }\n try {\n const query = new URLSearchParams({depositAddress});\n if (depositMemo) query.set(\"depositMemo\", depositMemo);\n const res = await fetch(\n `${apiBase}/status?${query.toString()}`,\n {headers: authHeaders(config.jwt), signal: timeoutSignal(12_000)},\n );\n if (!res.ok) return {state: \"pending\"};\n const s = (await res.json()) as {\n status?: string;\n swapDetails?: {destinationChainTxHashes?: unknown[]};\n };\n const map: Record<string, IntentStatus[\"state\"]> = {\n PENDING_DEPOSIT: \"pending\",\n KNOWN_DEPOSIT_TX: \"pending\",\n INCOMPLETE_DEPOSIT: \"pending\",\n PROCESSING: \"pending\",\n SUCCESS: \"completed\",\n FAILED: \"failed\",\n REFUNDED: \"refunded\",\n };\n const state = map[s.status ?? \"PENDING_DEPOSIT\"] ?? \"pending\";\n // KNOWN_DEPOSIT_TX: 1Click has the deposit tx (submitted, not yet\n // credited). Counted as received so a caller with no source hash of\n // its own does not expire a swap that is already on its way.\n const depositReceived = s.status === \"KNOWN_DEPOSIT_TX\" || s.status === \"PROCESSING\" || s.status === \"INCOMPLETE_DEPOSIT\";\n const destTx = txHashOf(s.swapDetails?.destinationChainTxHashes?.[0]);\n return {state, depositReceived, ...(destTx ? {destTxHash: destTx} : {})};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n"],"mappings":"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","names":["import_util","import_swap2_assets"]}
|
package/dist/protocol.d.cts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _anywalletkit_protocol_swap2_core_types from '@anywalletkit/protocol-swap2-core/types';
|
|
2
2
|
import { SingleProviderSwap2 } from '@anywalletkit/protocol-swap2-core/swap2/single';
|
|
3
|
-
import {
|
|
3
|
+
import { Swap2EngineConfig, Swap2Account } from '@anywalletkit/protocol-swap2-core/swap2/base';
|
|
4
4
|
import { NearIntentsProviderConfig } from './provider.cjs';
|
|
5
5
|
import './config.cjs';
|
|
6
6
|
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as _anywalletkit_protocol_swap2_core_types from '@anywalletkit/protocol-swap2-core/types';
|
|
2
2
|
import { SingleProviderSwap2 } from '@anywalletkit/protocol-swap2-core/swap2/single';
|
|
3
|
-
import {
|
|
3
|
+
import { Swap2EngineConfig, Swap2Account } from '@anywalletkit/protocol-swap2-core/swap2/base';
|
|
4
4
|
import { NearIntentsProviderConfig } from './provider.js';
|
|
5
5
|
import './config.js';
|
|
6
6
|
|
package/dist/protocol.js
CHANGED
package/dist/provider.cjs
CHANGED
|
@@ -309,6 +309,7 @@ function nearIntentsProvider(config = {}) {
|
|
|
309
309
|
const s = await res.json();
|
|
310
310
|
const map = {
|
|
311
311
|
PENDING_DEPOSIT: "pending",
|
|
312
|
+
KNOWN_DEPOSIT_TX: "pending",
|
|
312
313
|
INCOMPLETE_DEPOSIT: "pending",
|
|
313
314
|
PROCESSING: "pending",
|
|
314
315
|
SUCCESS: "completed",
|
|
@@ -316,7 +317,7 @@ function nearIntentsProvider(config = {}) {
|
|
|
316
317
|
REFUNDED: "refunded"
|
|
317
318
|
};
|
|
318
319
|
const state = map[s.status ?? "PENDING_DEPOSIT"] ?? "pending";
|
|
319
|
-
const depositReceived = s.status === "PROCESSING" || s.status === "INCOMPLETE_DEPOSIT";
|
|
320
|
+
const depositReceived = s.status === "KNOWN_DEPOSIT_TX" || s.status === "PROCESSING" || s.status === "INCOMPLETE_DEPOSIT";
|
|
320
321
|
const destTx = txHashOf(s.swapDetails?.destinationChainTxHashes?.[0]);
|
|
321
322
|
return { state, depositReceived, ...destTx ? { destTxHash: destTx } : {} };
|
|
322
323
|
} catch {
|
package/dist/provider.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/provider.ts","../src/config.ts","../src/activity.ts"],"sourcesContent":["import {nearIntents as cfg, nearIntentsChainRefusal, type NearIntentsSuspendedChains} from \"./config.js\";\nimport {describeNearIntentsActivity} from \"./activity.js\";\nimport {timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {CC_DEST, ccAsset, ccAssetByToken, ccChain} from \"@anywalletkit/swap2-assets\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * NEAR Intents (1Click) provider — the core route, broadest coverage. Ported\n * from a production 1Click integration:\n * dry quote → pricing preview; live quote → depositAddress the user funds\n * from any wallet; status polled by depositAddress.\n * Runs server-side, so the partner JWT stays here (no proxy needed). Defensive:\n * any API error yields a null quote so the provider drops out of that round.\n */\n\nconst ONE_CLICK_DEFAULT = \"https://1click.chaindefuser.com/v0\";\nconst QUOTE_TTL_MS = 55_000;\n\n/** intentId durably carries both status lookup keys (memo is quote-specific). */\nconst INTENT_PREFIX = \"near1click:\";\n\nfunction encodeIntent(depositAddress: string, depositMemo: string | null): string {\n return `${INTENT_PREFIX}${encodeURIComponent(depositAddress)}|${encodeURIComponent(depositMemo ?? \"\")}`;\n}\n\nfunction decodeIntent(intentId: string): {depositAddress: string; depositMemo?: string} {\n try {\n if (!intentId.startsWith(INTENT_PREFIX)) throw new Error(\"unsupported id version\");\n const raw = intentId.slice(INTENT_PREFIX.length);\n const parts = raw.split(\"|\");\n if (parts.length !== 2 || !parts[0]) throw new Error(\"invalid id shape\");\n const depositAddress = decodeURIComponent(parts[0]);\n const memo = decodeURIComponent(parts[1] ?? \"\");\n if (!depositAddress) throw new Error(\"empty deposit address\");\n return {depositAddress, ...(memo ? {depositMemo: memo} : {})};\n } catch {\n throw new Error(\"near-intents: malformed intent id\");\n }\n}\n\nfunction authHeaders(jwtOverride?: string): Record<string, string> {\n const h: Record<string, string> = {\"content-type\": \"application/json\", accept: \"application/json\"};\n const jwt = jwtOverride;\n if (jwt) h.authorization = `Bearer ${jwt}`;\n return h;\n}\n\n/** Our integrator fee, injected server-side when a recipient is configured. */\nfunction appFees(recipient?: string, bps?: number): {recipient: string; fee: number}[] | undefined {\n return recipient !== undefined && bps !== undefined ? [{recipient, fee: bps}] : undefined;\n}\n\n/**\n * Per-source deposit + refund config. Every live default keeps failed-swap\n * ownership on the caller's source-chain address.\n */\nfunction depositConfig(_sourceChain: string, refundAddress: string, _dry: boolean) {\n // Every source refunds to the caller's own source-chain address (Zcash\n // included — a t-address placeholder serves dry quotes since 2026-10-18).\n // Never redirect failed swaps to an integrator-owned NEAR account.\n return {depositType: \"ORIGIN_CHAIN\", refundType: \"ORIGIN_CHAIN\", refundTo: refundAddress};\n}\n\n/** Placeholder sender/recipient for dry quotes (1Click requires the fields). */\nconst PLACEHOLDER: Record<string, string> = {\n bitcoin: \"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq\",\n ton: \"UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ\",\n // NOT a token mint: with the USDC mint here, every dry quote whose ORIGIN\n // was Solana USDC answered 500 \"Internal server error\" (2026-10-09) — a\n // refund \"to the asset's own mint\" trips 1Click. The incinerator is a\n // plain, valid system address.\n solana: \"1nc1nerator11111111111111111111111111111111\",\n tron: \"TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9\",\n // NEAR refunds go to an account id; the registrar account always exists.\n near: \"near\",\n // A live transparent address (exchange hot wallet); dry quotes only.\n zcash: \"t1KfwsnwJeNRVjQGBDZhwKskpQbih2qx5Ua\",\n eip155: \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",\n};\n\nfunction placeholderFor(chain: string): string {\n return PLACEHOLDER[chain.split(\":\")[0] ?? \"\"] ?? PLACEHOLDER.eip155!;\n}\n\nfunction deadlineIn(minutes: number): string {\n return new Date(Date.now() + minutes * 60_000).toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n}\n\n/**\n * dest asset id for ANY chain in the catalog (inbound → Ethereum, or the step-2\n * off-ramp → any supported chain). Falls back to the Ethereum omft pattern for\n * a mainnet ERC-20 that isn't in the curated catalog.\n */\nfunction destAssetId(destChain: string, destToken: string): string | null {\n const asset = ccAssetByToken(destChain, destToken);\n if (asset) return asset.assetId;\n if (destChain === CC_DEST.caip2 && /^0x[0-9a-fA-F]{40}$/.test(destToken)) {\n return `nep141:eth-${destToken.toLowerCase()}.omft.near`;\n }\n return null;\n}\n\ntype OneClickQuote = {\n quote?: Record<string, unknown>;\n correlationId?: string;\n error?: string;\n message?: string;\n};\n\n/** 1Click returns tx hashes either as strings or {hash, explorerUrl}. */\nfunction txHashOf(entry: unknown): string | null {\n if (!entry) return null;\n if (typeof entry === \"string\") return entry;\n const h = (entry as {hash?: string}).hash;\n return typeof h === \"string\" ? h : null;\n}\n\n/** Explicit constructor configuration; no deployment environment is read. */\nexport interface NearIntentsProviderConfig {\n enabled?: boolean;\n apiUrl?: string;\n jwt?: string;\n feeRecipient?: string;\n feeBps?: number;\n /** Corridors the app has paused (caip2 → reason): refused up front, by name, until the app lifts them. */\n suspendedChains?: NearIntentsSuspendedChains;\n}\n\nexport function nearIntentsProvider(config: NearIntentsProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const parsedApiUrl = new URL(config.apiUrl ?? ONE_CLICK_DEFAULT);\n if (parsedApiUrl.protocol !== \"https:\" && parsedApiUrl.protocol !== \"http:\") {\n throw new Error(\"near-intents: apiUrl must use http or https\");\n }\n const apiBase = parsedApiUrl.toString().replace(/\\/$/, \"\");\n const hasRecipient = config.feeRecipient !== undefined;\n const hasBps = config.feeBps !== undefined;\n if (hasRecipient !== hasBps) throw new Error(\"near-intents: feeRecipient and feeBps must be configured together\");\n if (hasRecipient && (!config.feeRecipient!.trim() || !Number.isInteger(config.feeBps) || config.feeBps! <= 0 || config.feeBps! > 10_000)) {\n throw new Error(\"near-intents: fee config requires a recipient and feeBps between 1 and 10000\");\n }\n return {\n name: \"near_intents\",\n describeActivity: describeNearIntentsActivity,\n enabled: () => config.enabled ?? true,\n\n // Capability discovery comes from the provider itself, so it can run alone\n // or inside the optional aggregator without a central capability table.\n supportsChain: (chain: string) => cfg.supportsChain(chain),\n supportsChainPair: (fromChain: string, toChain: string) => cfg.supports(fromChain, toChain),\n supportsRoute(from: Asset, to: Asset): boolean {\n // Chain-level gate first (namespace, catalog listing, hand-suspended\n // corridors such as TON while the HOT bridge is dark) …\n if (!cfg.supports(from.chain, to.chain)) return false;\n // … then only pairs present in the curated catalog are offered — and only\n // those with a 1Click asset id (LI.FI-only tokens carry an empty assetId).\n // Both ends: a destination 1Click doesn't list (Unichain, MegaETH, …)\n // answered \"unknown asset\" on every quote (589 of the 2026-10-10 matrix).\n const asset = ccAsset(from.chain, from.token);\n return !!ccChain(from.chain) && !!asset?.assetId && !!destAssetId(to.chain, to.token);\n },\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n // Every refusal below names itself: on the server these lines are the\n // only visibility into WHY a live quote returned null (the wire answer\n // is just `null`), and \"no route\" bugs hide in exactly that silence.\n const refuse = (reason: string): null => {\n const detail = `${reason} [dry=${params.dry !== false} ${params.sourceChain}->${params.destChain} amount=${params.amountIn}]`;\n // Caller fields and 1Click text are untrusted: no control characters in server logs.\n console.warn(`near-intents: no quote — ${detail.replace(/[\\u0000-\\u001f\\u007f]/g, \" \")}`);\n params.onRefusal?.(detail);\n return null;\n };\n // Up-front, named refusals — no wire call for a corridor 1Click cannot\n // serve: a chain outside its list / suspended by hand, or a token the\n // catalog carries without a 1Click asset id (\"1Click does not list …\").\n const paused = config.suspendedChains ?? {};\n const chainRefusal = nearIntentsChainRefusal(params.sourceChain, paused) ?? nearIntentsChainRefusal(params.destChain, paused);\n if (chainRefusal) return refuse(chainRefusal);\n const origin = ccAsset(params.sourceChain, params.sourceToken);\n if (!origin?.assetId) return refuse(`1Click does not list ${params.sourceChain} ${params.sourceToken}`);\n const destination = destAssetId(params.destChain, params.destToken);\n if (!destination) return refuse(`1Click does not list ${params.destChain} ${params.destToken}`);\n const dry = params.dry !== false;\n // A live quote derives the deposit address from the refund config —\n // never create one without a real refund destination.\n const refund = params.refundAddress ?? (dry ? placeholderFor(params.sourceChain) : \"\");\n const dcfg = depositConfig(params.sourceChain, refund, dry);\n if (!dry && !dcfg.refundTo) return refuse(\"live quote without a refund address\");\n\n const requestedDeadline = deadlineIn(60);\n const body: Record<string, unknown> = {\n dry,\n // FLEX_INPUT (exchange flow): the address accepts any amount; amountIn\n // is just the pricing notional. Verified against the live API.\n swapType: params.flex ? \"FLEX_INPUT\" : \"EXACT_INPUT\",\n slippageTolerance: params.slippageBps ?? 100,\n originAsset: origin.assetId,\n depositType: dcfg.depositType,\n destinationAsset: destination,\n amount: params.amountIn,\n refundTo: dcfg.refundTo,\n refundType: dcfg.refundType,\n recipient: params.destAddress,\n recipientType: \"DESTINATION_CHAIN\",\n deadline: requestedDeadline,\n };\n const fees = appFees(config.feeRecipient, config.feeBps);\n if (fees) body.appFees = fees;\n\n try {\n // 1Click's solver auction flaps: the same body can answer 400 \"No\n // liquidity available\" and 201 seconds apart (observed live on\n // TON USDT -> ETH). A transient flap on the EXECUTION quote would\n // surface as a terminal \"no route\" right after a successful display\n // quote, so ride through it: up to two retries on liquidity flaps,\n // 5xx and network errors. Real rejections (bad address, unknown\n // asset) still fail on the first answer.\n let res: Response | null = null;\n let data: OneClickQuote = {};\n for (let attempt = 0; ; attempt++) {\n try {\n res = await fetch(`${apiBase}/quote`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify(body),\n signal: signal ?? timeoutSignal(12_000),\n });\n data = (await res.json().catch(() => ({}))) as OneClickQuote;\n } catch (err) {\n if (attempt >= 2 || signal?.aborted) throw err;\n res = null;\n }\n if (res?.ok) break;\n const flaky =\n res === null ||\n res.status >= 500 ||\n (res.status === 400 && /no liquidity/i.test(String(data.message ?? \"\")));\n if (!flaky || attempt >= 2 || signal?.aborted) break;\n await new Promise((resolve) => setTimeout(resolve, 500 * (attempt + 1)));\n }\n if (!res?.ok) return refuse(`1Click ${res?.status ?? \"network error\"}: ${String(data.message ?? \"\").slice(0, 200)}`);\n const q = (data.quote ?? {}) as Record<string, unknown>;\n\n const depositAddress = typeof q.depositAddress === \"string\" ? q.depositAddress : \"\";\n if (!dry && !depositAddress) return refuse(\"live quote came back without a deposit address\");\n const inUsd = Number.parseFloat(String(q.amountInUsd ?? \"0\"));\n const outUsd = Number.parseFloat(String(q.amountOutUsd ?? \"0\"));\n const parsedDeadline = Date.parse(String(q.deadline ?? \"\"));\n if (!dry && (!Number.isFinite(parsedDeadline) || parsedDeadline <= Date.now())) return refuse(`unusable deadline ${String(q.deadline)}`);\n const deadline = Number.isFinite(parsedDeadline) && parsedDeadline > Date.now()\n ? Math.min(parsedDeadline, Date.now() + QUOTE_TTL_MS)\n : Date.now() + QUOTE_TTL_MS;\n\n if (q.amountIn !== undefined && String(q.amountIn) !== params.amountIn) return refuse(`amountIn mismatch (${String(q.amountIn)} vs ${params.amountIn})`);\n\n // amountOut is optimistic, not a guaranteed floor. Live execution must\n // not fabricate a minimum when the provider omits it.\n if (q.minAmountOut === undefined || q.minAmountOut === null) return refuse(\"quote has no minAmountOut\");\n const minDestAmount = String(q.minAmountOut);\n if (params.minAmountOut !== undefined && BigInt(minDestAmount) < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${minDestAmount} < floor=${params.minAmountOut})`);\n const depositMemo =\n (typeof q.depositMemo === \"string\" && q.depositMemo) ||\n (typeof q.memo === \"string\" && q.memo) ||\n null;\n return {\n provider: \"near_intents\",\n intentId: depositAddress ? encodeIntent(depositAddress, depositMemo) : `dry:${crypto.randomUUID()}`,\n depositAddress,\n depositMemo,\n sourceAmount: params.amountIn,\n destAmount: String(q.amountOut ?? \"0\"),\n minDestAmount,\n feeUsd: Math.max(0, inUsd - outUsd),\n etaSeconds: Number(q.timeEstimate ?? 60),\n reliability: 0.95,\n validUntilMs: deadline,\n };\n } catch (err) {\n return refuse(`threw: ${err instanceof Error ? err.message.slice(0, 200) : String(err).slice(0, 200)}`);\n }\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n return {\n chain: \"\",\n to: quote.depositAddress,\n value: quote.sourceAmount,\n ...(quote.depositMemo ? {memo: quote.depositMemo} : {}),\n };\n },\n\n async notifyDeposit(intentId: string, txHash: string): Promise<void> {\n const {depositAddress} = decodeIntent(intentId);\n const res = await fetch(`${apiBase}/deposit/submit`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify({depositAddress, txHash}),\n signal: timeoutSignal(12_000),\n });\n if (!res.ok) throw new Error(`near-intents: deposit notification failed (${res.status})`);\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n const {depositAddress, depositMemo} = decodeIntent(ref.intentId);\n // Durable retry: BaseSwap2Protocol embeds the source hash in the swap2\n // id. If the post-broadcast notify failed, every status poll retries it.\n if (ref.sourceTxHash) {\n await this.notifyDeposit?.(ref.intentId, ref.sourceTxHash).catch(() => {});\n }\n try {\n const query = new URLSearchParams({depositAddress});\n if (depositMemo) query.set(\"depositMemo\", depositMemo);\n const res = await fetch(\n `${apiBase}/status?${query.toString()}`,\n {headers: authHeaders(config.jwt), signal: timeoutSignal(12_000)},\n );\n if (!res.ok) return {state: \"pending\"};\n const s = (await res.json()) as {\n status?: string;\n swapDetails?: {destinationChainTxHashes?: unknown[]};\n };\n const map: Record<string, IntentStatus[\"state\"]> = {\n PENDING_DEPOSIT: \"pending\",\n INCOMPLETE_DEPOSIT: \"pending\",\n PROCESSING: \"pending\",\n SUCCESS: \"completed\",\n FAILED: \"failed\",\n REFUNDED: \"refunded\",\n };\n const state = map[s.status ?? \"PENDING_DEPOSIT\"] ?? \"pending\";\n const depositReceived = s.status === \"PROCESSING\" || s.status === \"INCOMPLETE_DEPOSIT\";\n const destTx = txHashOf(s.swapDetails?.destinationChainTxHashes?.[0]);\n return {state, depositReceived, ...(destTx ? {destTxHash: destTx} : {})};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n","import {namespace} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {ccChain} from \"@anywalletkit/swap2-assets\";\n\n// ── NEAR Intents (1Click) — core, broadest coverage ─────────────────────────\nconst NEAR_INTENTS_NS = new Set([\n \"eip155\", \"solana\", \"tron\", \"bitcoin\", \"near\", \"sui\", \"ton\", \"zcash\",\n \"litecoin\", \"doge\", \"xrp\", \"bch\", \"cardano\", \"stellar\", \"aptos\",\n]);\n\n/**\n * Corridors the APP has paused (caip2 → why), passed in through the provider\n * config: a venue-side degradation (1Click's HOT omni-bridge assets answering\n * \"not available\" for days) is an operational switch, not SDK knowledge — the\n * wallet flips an env var and lifts it the same way when the venue recovers.\n */\nexport type NearIntentsSuspendedChains = Readonly<Record<string, string>>;\n\n/** Why a chain is refused up front, or null when 1Click can serve it. */\nexport function nearIntentsChainRefusal(chain: string, suspended: NearIntentsSuspendedChains = {}): string | null {\n if (!NEAR_INTENTS_NS.has(namespace(chain))) return `1Click does not serve ${chain}`;\n const why = suspended[chain];\n if (why) return `1Click corridor paused by the app: ${chain} — ${why}`;\n // A chain the catalog knows but carries no 1Click asset id for (World Chain,\n // Sei, Ink, Plume, X Layer, Unichain, MegaETH, Linea, Sonic, …) is LI.FI /\n // CCTP territory: the eip155 namespace alone used to claim it, and every\n // quote then died as \"unknown asset\" (2026-10-16 funded run).\n const listed = ccChain(chain)?.assets.some((a) => a.assetId.length > 0) ?? false;\n return listed ? null : `1Click does not list ${chain}`;\n}\n\nexport const nearIntents = {\n enabled: () => true,\n // Routes between any pair of 1Click-listed chains. 1Click is a NEAR-intents\n // solver network — it settles non-EVM↔non-EVM directly (BTC→Solana, Tron→\n // Base …), so this pre-filter must NOT require an EVM leg (the old \"vault\n // leg is always EVM\" assumption of the off-ramp flow silently blocked those\n // swap routes). A chain counts as listed when the shared catalog carries at\n // least one 1Click asset id for it and it is not suspended above; `getQuote`\n // is the real per-pair check and fail-closes (returns null, naming why) for\n // any pair 1Click can't actually route.\n // 2026-08 sweep: 1Click added LTC/DOGE/XRP/BCH/ADA/XLM/APT (+ the EVM\n // additions Avalanche/Scroll/Berachain, covered by the catalog ids).\n supportsChain(chain: string): boolean {\n return nearIntentsChainRefusal(chain) === null;\n },\n supports(from: string, to: string): boolean {\n return this.supportsChain(from) && this.supportsChain(to);\n },\n};\n","/**\n * Activity recognition for NEAR Intents (1Click).\n *\n * The source leg on EVM / TON / Solana / Tron / BTC is a plain transfer to a\n * one-time 1Click deposit address, and the destination leg is a plain transfer\n * from a solver / bridge account that changes per swap — neither carries a\n * stable on-chain marker, so they are NOT recognizable offline. The kit's\n * intent journal (the `intentId` returned by `swap2()`) ties those legs back to\n * the swap; this hook only answers for the legs that do have a fixed\n * counterparty: on NEAR itself, deposits into and withdrawals out of the\n * `intents.near` verifier contract (NEP-141 `ft_transfer_call` / `ft_withdraw`).\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {describeSwapLike} from \"@anywalletkit/protocol-swap2-core/activity\";\n\nexport const NEAR_INTENTS_MODULE = \"@anywalletkit/protocol-swap2-near-intents\";\n\n/** The NEAR Intents verifier / settlement contract. */\nexport const NEAR_INTENTS_CONTRACT = \"intents.near\";\n\nexport function describeNearIntentsActivity(tx: ChainTx, ctx: DescribeActivityContext): ActivityItem | null {\n if (!tx.chain.startsWith(\"near:\")) return null;\n const isOwn = (a: string) => ctx.own.has(a);\n const touches = tx.transfers.some((t) => (t.from === NEAR_INTENTS_CONTRACT && isOwn(t.to)) || (t.to === NEAR_INTENTS_CONTRACT && isOwn(t.from)));\n if (!touches) return null;\n return describeSwapLike(tx, ctx, {\n protocol: NEAR_INTENTS_MODULE,\n subtitle: \"NEAR Intents\",\n kind: \"bridge\",\n counterparty: NEAR_INTENTS_CONTRACT,\n inSuffix: \"via NEAR Intents\",\n });\n}\n"],"mappings":"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","names":["import_util","import_swap2_assets"]}
|
|
1
|
+
{"version":3,"sources":["../src/provider.ts","../src/config.ts","../src/activity.ts"],"sourcesContent":["import {nearIntents as cfg, nearIntentsChainRefusal, type NearIntentsSuspendedChains} from \"./config.js\";\nimport {describeNearIntentsActivity} from \"./activity.js\";\nimport {timeoutSignal} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {CC_DEST, ccAsset, ccAssetByToken, ccChain} from \"@anywalletkit/swap2-assets\";\nimport type {Asset, CrossChainProvider, IntentRef, IntentStatus, Quote, QuoteParams, UnsignedTx} from \"@anywalletkit/protocol-swap2-core/types\";\n\n/**\n * NEAR Intents (1Click) provider — the core route, broadest coverage. Ported\n * from a production 1Click integration:\n * dry quote → pricing preview; live quote → depositAddress the user funds\n * from any wallet; status polled by depositAddress.\n * Runs server-side, so the partner JWT stays here (no proxy needed). Defensive:\n * any API error yields a null quote so the provider drops out of that round.\n */\n\nconst ONE_CLICK_DEFAULT = \"https://1click.chaindefuser.com/v0\";\nconst QUOTE_TTL_MS = 55_000;\n\n/** intentId durably carries both status lookup keys (memo is quote-specific). */\nconst INTENT_PREFIX = \"near1click:\";\n\nfunction encodeIntent(depositAddress: string, depositMemo: string | null): string {\n return `${INTENT_PREFIX}${encodeURIComponent(depositAddress)}|${encodeURIComponent(depositMemo ?? \"\")}`;\n}\n\nfunction decodeIntent(intentId: string): {depositAddress: string; depositMemo?: string} {\n try {\n if (!intentId.startsWith(INTENT_PREFIX)) throw new Error(\"unsupported id version\");\n const raw = intentId.slice(INTENT_PREFIX.length);\n const parts = raw.split(\"|\");\n if (parts.length !== 2 || !parts[0]) throw new Error(\"invalid id shape\");\n const depositAddress = decodeURIComponent(parts[0]);\n const memo = decodeURIComponent(parts[1] ?? \"\");\n if (!depositAddress) throw new Error(\"empty deposit address\");\n return {depositAddress, ...(memo ? {depositMemo: memo} : {})};\n } catch {\n throw new Error(\"near-intents: malformed intent id\");\n }\n}\n\nfunction authHeaders(jwtOverride?: string): Record<string, string> {\n const h: Record<string, string> = {\"content-type\": \"application/json\", accept: \"application/json\"};\n const jwt = jwtOverride;\n if (jwt) h.authorization = `Bearer ${jwt}`;\n return h;\n}\n\n/** Our integrator fee, injected server-side when a recipient is configured. */\nfunction appFees(recipient?: string, bps?: number): {recipient: string; fee: number}[] | undefined {\n return recipient !== undefined && bps !== undefined ? [{recipient, fee: bps}] : undefined;\n}\n\n/**\n * Per-source deposit + refund config. Every live default keeps failed-swap\n * ownership on the caller's source-chain address.\n */\nfunction depositConfig(_sourceChain: string, refundAddress: string, _dry: boolean) {\n // Every source refunds to the caller's own source-chain address (Zcash\n // included — a t-address placeholder serves dry quotes since 2026-10-18).\n // Never redirect failed swaps to an integrator-owned NEAR account.\n return {depositType: \"ORIGIN_CHAIN\", refundType: \"ORIGIN_CHAIN\", refundTo: refundAddress};\n}\n\n/** Placeholder sender/recipient for dry quotes (1Click requires the fields). */\nconst PLACEHOLDER: Record<string, string> = {\n bitcoin: \"bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq\",\n ton: \"UQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJKZ\",\n // NOT a token mint: with the USDC mint here, every dry quote whose ORIGIN\n // was Solana USDC answered 500 \"Internal server error\" (2026-10-09) — a\n // refund \"to the asset's own mint\" trips 1Click. The incinerator is a\n // plain, valid system address.\n solana: \"1nc1nerator11111111111111111111111111111111\",\n tron: \"TN3W4H6rK2ce4vX9YnFQHwKENnHjoxb3m9\",\n // NEAR refunds go to an account id; the registrar account always exists.\n near: \"near\",\n // A live transparent address (exchange hot wallet); dry quotes only.\n zcash: \"t1KfwsnwJeNRVjQGBDZhwKskpQbih2qx5Ua\",\n eip155: \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\",\n};\n\nfunction placeholderFor(chain: string): string {\n return PLACEHOLDER[chain.split(\":\")[0] ?? \"\"] ?? PLACEHOLDER.eip155!;\n}\n\nfunction deadlineIn(minutes: number): string {\n return new Date(Date.now() + minutes * 60_000).toISOString().replace(/\\.\\d{3}Z$/, \"Z\");\n}\n\n/**\n * dest asset id for ANY chain in the catalog (inbound → Ethereum, or the step-2\n * off-ramp → any supported chain). Falls back to the Ethereum omft pattern for\n * a mainnet ERC-20 that isn't in the curated catalog.\n */\nfunction destAssetId(destChain: string, destToken: string): string | null {\n const asset = ccAssetByToken(destChain, destToken);\n if (asset) return asset.assetId;\n if (destChain === CC_DEST.caip2 && /^0x[0-9a-fA-F]{40}$/.test(destToken)) {\n return `nep141:eth-${destToken.toLowerCase()}.omft.near`;\n }\n return null;\n}\n\ntype OneClickQuote = {\n quote?: Record<string, unknown>;\n correlationId?: string;\n error?: string;\n message?: string;\n};\n\n/** 1Click returns tx hashes either as strings or {hash, explorerUrl}. */\nfunction txHashOf(entry: unknown): string | null {\n if (!entry) return null;\n if (typeof entry === \"string\") return entry;\n const h = (entry as {hash?: string}).hash;\n return typeof h === \"string\" ? h : null;\n}\n\n/** Explicit constructor configuration; no deployment environment is read. */\nexport interface NearIntentsProviderConfig {\n enabled?: boolean;\n apiUrl?: string;\n jwt?: string;\n feeRecipient?: string;\n feeBps?: number;\n /** Corridors the app has paused (caip2 → reason): refused up front, by name, until the app lifts them. */\n suspendedChains?: NearIntentsSuspendedChains;\n}\n\nexport function nearIntentsProvider(config: NearIntentsProviderConfig = {}): CrossChainProvider {\n config = Object.freeze({...config});\n const parsedApiUrl = new URL(config.apiUrl ?? ONE_CLICK_DEFAULT);\n if (parsedApiUrl.protocol !== \"https:\" && parsedApiUrl.protocol !== \"http:\") {\n throw new Error(\"near-intents: apiUrl must use http or https\");\n }\n const apiBase = parsedApiUrl.toString().replace(/\\/$/, \"\");\n const hasRecipient = config.feeRecipient !== undefined;\n const hasBps = config.feeBps !== undefined;\n if (hasRecipient !== hasBps) throw new Error(\"near-intents: feeRecipient and feeBps must be configured together\");\n if (hasRecipient && (!config.feeRecipient!.trim() || !Number.isInteger(config.feeBps) || config.feeBps! <= 0 || config.feeBps! > 10_000)) {\n throw new Error(\"near-intents: fee config requires a recipient and feeBps between 1 and 10000\");\n }\n return {\n name: \"near_intents\",\n describeActivity: describeNearIntentsActivity,\n enabled: () => config.enabled ?? true,\n\n // Capability discovery comes from the provider itself, so it can run alone\n // or inside the optional aggregator without a central capability table.\n supportsChain: (chain: string) => cfg.supportsChain(chain),\n supportsChainPair: (fromChain: string, toChain: string) => cfg.supports(fromChain, toChain),\n supportsRoute(from: Asset, to: Asset): boolean {\n // Chain-level gate first (namespace, catalog listing, hand-suspended\n // corridors such as TON while the HOT bridge is dark) …\n if (!cfg.supports(from.chain, to.chain)) return false;\n // … then only pairs present in the curated catalog are offered — and only\n // those with a 1Click asset id (LI.FI-only tokens carry an empty assetId).\n // Both ends: a destination 1Click doesn't list (Unichain, MegaETH, …)\n // answered \"unknown asset\" on every quote (589 of the 2026-10-10 matrix).\n const asset = ccAsset(from.chain, from.token);\n return !!ccChain(from.chain) && !!asset?.assetId && !!destAssetId(to.chain, to.token);\n },\n\n async getQuote(params: QuoteParams, signal?: AbortSignal): Promise<Quote | null> {\n // Every refusal below names itself: on the server these lines are the\n // only visibility into WHY a live quote returned null (the wire answer\n // is just `null`), and \"no route\" bugs hide in exactly that silence.\n const refuse = (reason: string): null => {\n const detail = `${reason} [dry=${params.dry !== false} ${params.sourceChain}->${params.destChain} amount=${params.amountIn}]`;\n // Caller fields and 1Click text are untrusted: no control characters in server logs.\n console.warn(`near-intents: no quote — ${detail.replace(/[\\u0000-\\u001f\\u007f]/g, \" \")}`);\n params.onRefusal?.(detail);\n return null;\n };\n // Up-front, named refusals — no wire call for a corridor 1Click cannot\n // serve: a chain outside its list / suspended by hand, or a token the\n // catalog carries without a 1Click asset id (\"1Click does not list …\").\n const paused = config.suspendedChains ?? {};\n const chainRefusal = nearIntentsChainRefusal(params.sourceChain, paused) ?? nearIntentsChainRefusal(params.destChain, paused);\n if (chainRefusal) return refuse(chainRefusal);\n const origin = ccAsset(params.sourceChain, params.sourceToken);\n if (!origin?.assetId) return refuse(`1Click does not list ${params.sourceChain} ${params.sourceToken}`);\n const destination = destAssetId(params.destChain, params.destToken);\n if (!destination) return refuse(`1Click does not list ${params.destChain} ${params.destToken}`);\n const dry = params.dry !== false;\n // A live quote derives the deposit address from the refund config —\n // never create one without a real refund destination.\n const refund = params.refundAddress ?? (dry ? placeholderFor(params.sourceChain) : \"\");\n const dcfg = depositConfig(params.sourceChain, refund, dry);\n if (!dry && !dcfg.refundTo) return refuse(\"live quote without a refund address\");\n\n const requestedDeadline = deadlineIn(60);\n const body: Record<string, unknown> = {\n dry,\n // FLEX_INPUT (exchange flow): the address accepts any amount; amountIn\n // is just the pricing notional. Verified against the live API.\n swapType: params.flex ? \"FLEX_INPUT\" : \"EXACT_INPUT\",\n slippageTolerance: params.slippageBps ?? 100,\n originAsset: origin.assetId,\n depositType: dcfg.depositType,\n destinationAsset: destination,\n amount: params.amountIn,\n refundTo: dcfg.refundTo,\n refundType: dcfg.refundType,\n recipient: params.destAddress,\n recipientType: \"DESTINATION_CHAIN\",\n deadline: requestedDeadline,\n };\n const fees = appFees(config.feeRecipient, config.feeBps);\n if (fees) body.appFees = fees;\n\n try {\n // 1Click's solver auction flaps: the same body can answer 400 \"No\n // liquidity available\" and 201 seconds apart (observed live on\n // TON USDT -> ETH). A transient flap on the EXECUTION quote would\n // surface as a terminal \"no route\" right after a successful display\n // quote, so ride through it: up to two retries on liquidity flaps,\n // 5xx and network errors. Real rejections (bad address, unknown\n // asset) still fail on the first answer.\n let res: Response | null = null;\n let data: OneClickQuote = {};\n for (let attempt = 0; ; attempt++) {\n try {\n res = await fetch(`${apiBase}/quote`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify(body),\n signal: signal ?? timeoutSignal(12_000),\n });\n data = (await res.json().catch(() => ({}))) as OneClickQuote;\n } catch (err) {\n if (attempt >= 2 || signal?.aborted) throw err;\n res = null;\n }\n if (res?.ok) break;\n const flaky =\n res === null ||\n res.status >= 500 ||\n (res.status === 400 && /no liquidity/i.test(String(data.message ?? \"\")));\n if (!flaky || attempt >= 2 || signal?.aborted) break;\n await new Promise((resolve) => setTimeout(resolve, 500 * (attempt + 1)));\n }\n if (!res?.ok) return refuse(`1Click ${res?.status ?? \"network error\"}: ${String(data.message ?? \"\").slice(0, 200)}`);\n const q = (data.quote ?? {}) as Record<string, unknown>;\n\n const depositAddress = typeof q.depositAddress === \"string\" ? q.depositAddress : \"\";\n if (!dry && !depositAddress) return refuse(\"live quote came back without a deposit address\");\n const inUsd = Number.parseFloat(String(q.amountInUsd ?? \"0\"));\n const outUsd = Number.parseFloat(String(q.amountOutUsd ?? \"0\"));\n const parsedDeadline = Date.parse(String(q.deadline ?? \"\"));\n if (!dry && (!Number.isFinite(parsedDeadline) || parsedDeadline <= Date.now())) return refuse(`unusable deadline ${String(q.deadline)}`);\n const deadline = Number.isFinite(parsedDeadline) && parsedDeadline > Date.now()\n ? Math.min(parsedDeadline, Date.now() + QUOTE_TTL_MS)\n : Date.now() + QUOTE_TTL_MS;\n\n if (q.amountIn !== undefined && String(q.amountIn) !== params.amountIn) return refuse(`amountIn mismatch (${String(q.amountIn)} vs ${params.amountIn})`);\n\n // amountOut is optimistic, not a guaranteed floor. Live execution must\n // not fabricate a minimum when the provider omits it.\n if (q.minAmountOut === undefined || q.minAmountOut === null) return refuse(\"quote has no minAmountOut\");\n const minDestAmount = String(q.minAmountOut);\n if (params.minAmountOut !== undefined && BigInt(minDestAmount) < BigInt(params.minAmountOut)) return refuse(`floor breach (min=${minDestAmount} < floor=${params.minAmountOut})`);\n const depositMemo =\n (typeof q.depositMemo === \"string\" && q.depositMemo) ||\n (typeof q.memo === \"string\" && q.memo) ||\n null;\n return {\n provider: \"near_intents\",\n intentId: depositAddress ? encodeIntent(depositAddress, depositMemo) : `dry:${crypto.randomUUID()}`,\n depositAddress,\n depositMemo,\n sourceAmount: params.amountIn,\n destAmount: String(q.amountOut ?? \"0\"),\n minDestAmount,\n feeUsd: Math.max(0, inUsd - outUsd),\n etaSeconds: Number(q.timeEstimate ?? 60),\n reliability: 0.95,\n validUntilMs: deadline,\n };\n } catch (err) {\n return refuse(`threw: ${err instanceof Error ? err.message.slice(0, 200) : String(err).slice(0, 200)}`);\n }\n },\n\n async buildDeposit(quote: Quote): Promise<UnsignedTx> {\n return {\n chain: \"\",\n to: quote.depositAddress,\n value: quote.sourceAmount,\n ...(quote.depositMemo ? {memo: quote.depositMemo} : {}),\n };\n },\n\n async notifyDeposit(intentId: string, txHash: string): Promise<void> {\n const {depositAddress} = decodeIntent(intentId);\n const res = await fetch(`${apiBase}/deposit/submit`, {\n method: \"POST\",\n headers: authHeaders(config.jwt),\n body: JSON.stringify({depositAddress, txHash}),\n signal: timeoutSignal(12_000),\n });\n if (!res.ok) throw new Error(`near-intents: deposit notification failed (${res.status})`);\n },\n\n async trackIntent(ref: IntentRef): Promise<IntentStatus> {\n const {depositAddress, depositMemo} = decodeIntent(ref.intentId);\n // Durable retry: BaseSwap2Protocol embeds the source hash in the swap2\n // id. If the post-broadcast notify failed, every status poll retries it.\n if (ref.sourceTxHash) {\n await this.notifyDeposit?.(ref.intentId, ref.sourceTxHash).catch(() => {});\n }\n try {\n const query = new URLSearchParams({depositAddress});\n if (depositMemo) query.set(\"depositMemo\", depositMemo);\n const res = await fetch(\n `${apiBase}/status?${query.toString()}`,\n {headers: authHeaders(config.jwt), signal: timeoutSignal(12_000)},\n );\n if (!res.ok) return {state: \"pending\"};\n const s = (await res.json()) as {\n status?: string;\n swapDetails?: {destinationChainTxHashes?: unknown[]};\n };\n const map: Record<string, IntentStatus[\"state\"]> = {\n PENDING_DEPOSIT: \"pending\",\n KNOWN_DEPOSIT_TX: \"pending\",\n INCOMPLETE_DEPOSIT: \"pending\",\n PROCESSING: \"pending\",\n SUCCESS: \"completed\",\n FAILED: \"failed\",\n REFUNDED: \"refunded\",\n };\n const state = map[s.status ?? \"PENDING_DEPOSIT\"] ?? \"pending\";\n // KNOWN_DEPOSIT_TX: 1Click has the deposit tx (submitted, not yet\n // credited). Counted as received so a caller with no source hash of\n // its own does not expire a swap that is already on its way.\n const depositReceived = s.status === \"KNOWN_DEPOSIT_TX\" || s.status === \"PROCESSING\" || s.status === \"INCOMPLETE_DEPOSIT\";\n const destTx = txHashOf(s.swapDetails?.destinationChainTxHashes?.[0]);\n return {state, depositReceived, ...(destTx ? {destTxHash: destTx} : {})};\n } catch {\n return {state: \"pending\"};\n }\n },\n };\n}\n","import {namespace} from \"@anywalletkit/protocol-swap2-core/util\";\nimport {ccChain} from \"@anywalletkit/swap2-assets\";\n\n// ── NEAR Intents (1Click) — core, broadest coverage ─────────────────────────\nconst NEAR_INTENTS_NS = new Set([\n \"eip155\", \"solana\", \"tron\", \"bitcoin\", \"near\", \"sui\", \"ton\", \"zcash\",\n \"litecoin\", \"doge\", \"xrp\", \"bch\", \"cardano\", \"stellar\", \"aptos\",\n]);\n\n/**\n * Corridors the APP has paused (caip2 → why), passed in through the provider\n * config: a venue-side degradation (1Click's HOT omni-bridge assets answering\n * \"not available\" for days) is an operational switch, not SDK knowledge — the\n * wallet flips an env var and lifts it the same way when the venue recovers.\n */\nexport type NearIntentsSuspendedChains = Readonly<Record<string, string>>;\n\n/** Why a chain is refused up front, or null when 1Click can serve it. */\nexport function nearIntentsChainRefusal(chain: string, suspended: NearIntentsSuspendedChains = {}): string | null {\n if (!NEAR_INTENTS_NS.has(namespace(chain))) return `1Click does not serve ${chain}`;\n const why = suspended[chain];\n if (why) return `1Click corridor paused by the app: ${chain} — ${why}`;\n // A chain the catalog knows but carries no 1Click asset id for (World Chain,\n // Sei, Ink, Plume, X Layer, Unichain, MegaETH, Linea, Sonic, …) is LI.FI /\n // CCTP territory: the eip155 namespace alone used to claim it, and every\n // quote then died as \"unknown asset\" (2026-10-16 funded run).\n const listed = ccChain(chain)?.assets.some((a) => a.assetId.length > 0) ?? false;\n return listed ? null : `1Click does not list ${chain}`;\n}\n\nexport const nearIntents = {\n enabled: () => true,\n // Routes between any pair of 1Click-listed chains. 1Click is a NEAR-intents\n // solver network — it settles non-EVM↔non-EVM directly (BTC→Solana, Tron→\n // Base …), so this pre-filter must NOT require an EVM leg (the old \"vault\n // leg is always EVM\" assumption of the off-ramp flow silently blocked those\n // swap routes). A chain counts as listed when the shared catalog carries at\n // least one 1Click asset id for it and it is not suspended above; `getQuote`\n // is the real per-pair check and fail-closes (returns null, naming why) for\n // any pair 1Click can't actually route.\n // 2026-08 sweep: 1Click added LTC/DOGE/XRP/BCH/ADA/XLM/APT (+ the EVM\n // additions Avalanche/Scroll/Berachain, covered by the catalog ids).\n supportsChain(chain: string): boolean {\n return nearIntentsChainRefusal(chain) === null;\n },\n supports(from: string, to: string): boolean {\n return this.supportsChain(from) && this.supportsChain(to);\n },\n};\n","/**\n * Activity recognition for NEAR Intents (1Click).\n *\n * The source leg on EVM / TON / Solana / Tron / BTC is a plain transfer to a\n * one-time 1Click deposit address, and the destination leg is a plain transfer\n * from a solver / bridge account that changes per swap — neither carries a\n * stable on-chain marker, so they are NOT recognizable offline. The kit's\n * intent journal (the `intentId` returned by `swap2()`) ties those legs back to\n * the swap; this hook only answers for the legs that do have a fixed\n * counterparty: on NEAR itself, deposits into and withdrawals out of the\n * `intents.near` verifier contract (NEP-141 `ft_transfer_call` / `ft_withdraw`).\n */\nimport type {ActivityItem, ChainTx, DescribeActivityContext} from \"@anywalletkit/core\";\nimport {describeSwapLike} from \"@anywalletkit/protocol-swap2-core/activity\";\n\nexport const NEAR_INTENTS_MODULE = \"@anywalletkit/protocol-swap2-near-intents\";\n\n/** The NEAR Intents verifier / settlement contract. */\nexport const NEAR_INTENTS_CONTRACT = \"intents.near\";\n\nexport function describeNearIntentsActivity(tx: ChainTx, ctx: DescribeActivityContext): ActivityItem | null {\n if (!tx.chain.startsWith(\"near:\")) return null;\n const isOwn = (a: string) => ctx.own.has(a);\n const touches = tx.transfers.some((t) => (t.from === NEAR_INTENTS_CONTRACT && isOwn(t.to)) || (t.to === NEAR_INTENTS_CONTRACT && isOwn(t.from)));\n if (!touches) return null;\n return describeSwapLike(tx, ctx, {\n protocol: NEAR_INTENTS_MODULE,\n subtitle: \"NEAR Intents\",\n kind: \"bridge\",\n counterparty: NEAR_INTENTS_CONTRACT,\n inSuffix: \"via NEAR Intents\",\n });\n}\n"],"mappings":"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","names":["import_util","import_swap2_assets"]}
|
package/dist/provider.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@anywalletkit/protocol-swap2-near-intents",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "0.1.9",
|
|
4
|
+
"description": "NEAR Intents (1Click) cross-chain swaps for Any Wallet Kit: the wallet sends to a one-time deposit address, solvers settle on NEAR and deliver on the destination chain; standalone or as a provider of the swap2 router.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://docs.anywallet.tech",
|
|
7
7
|
"bugs": {
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
},
|
|
15
15
|
"type": "module",
|
|
16
16
|
"engines": {
|
|
17
|
-
"node": ">=
|
|
17
|
+
"node": ">=22"
|
|
18
18
|
},
|
|
19
19
|
"sideEffects": false,
|
|
20
20
|
"main": "./dist/index.cjs",
|
|
@@ -49,19 +49,27 @@
|
|
|
49
49
|
"module.json"
|
|
50
50
|
],
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@anywalletkit/protocol-swap2-core": "0.
|
|
53
|
-
"@anywalletkit/swap2-assets": "0.2.
|
|
52
|
+
"@anywalletkit/protocol-swap2-core": "0.6.1",
|
|
53
|
+
"@anywalletkit/swap2-assets": "0.2.2"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@anywalletkit/core": "0.
|
|
56
|
+
"@anywalletkit/core": "0.6.1"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|
|
59
59
|
"@types/node": "^22",
|
|
60
60
|
"vitest": "^5.0.3",
|
|
61
|
-
"@anywalletkit/conformance": "0.4.
|
|
62
|
-
"@anywalletkit/core": "0.
|
|
61
|
+
"@anywalletkit/conformance": "0.4.4",
|
|
62
|
+
"@anywalletkit/core": "0.6.1"
|
|
63
63
|
},
|
|
64
|
-
"keywords": [
|
|
64
|
+
"keywords": [
|
|
65
|
+
"swap2",
|
|
66
|
+
"swap",
|
|
67
|
+
"bridge",
|
|
68
|
+
"near-intents",
|
|
69
|
+
"1click",
|
|
70
|
+
"cross-chain",
|
|
71
|
+
"anywalletkit"
|
|
72
|
+
],
|
|
65
73
|
"publishConfig": {
|
|
66
74
|
"access": "public",
|
|
67
75
|
"provenance": true
|
|
File without changes
|