@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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  nearIntentsProvider
3
- } from "./chunk-DA4EDMKN.js";
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-HUH3GOAM.js.map
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-DA4EDMKN.js.map
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 {
@@ -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
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  NearIntentsSwap2Protocol
3
- } from "./chunk-HUH3GOAM.js";
3
+ } from "./chunk-GKPYIWQ7.js";
4
4
  import {
5
5
  nearIntentsProvider
6
- } from "./chunk-DA4EDMKN.js";
6
+ } from "./chunk-TCWV5CH4.js";
7
7
  import {
8
8
  nearIntents,
9
9
  nearIntentsChainRefusal
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 {
@@ -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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAkC;;;ACAlC,kBAAwB;AACxB,0BAAsB;AAGtB,IAAM,kBAAkB,oBAAI,IAAI;AAAA,EAC9B;AAAA,EAAU;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAW;AAAA,EAAQ;AAAA,EAAO;AAAA,EAAO;AAAA,EAC7D;AAAA,EAAY;AAAA,EAAQ;AAAA,EAAO;AAAA,EAAO;AAAA,EAAW;AAAA,EAAW;AAC1D,CAAC;AAWM,SAAS,wBAAwB,OAAe,YAAwC,CAAC,GAAkB;AAChH,MAAI,CAAC,gBAAgB,QAAI,uBAAU,KAAK,CAAC,EAAG,QAAO,yBAAyB,KAAK;AACjF,QAAM,MAAM,UAAU,KAAK;AAC3B,MAAI,IAAK,QAAO,sCAAsC,KAAK,WAAM,GAAG;AAKpE,QAAM,aAAS,6BAAQ,KAAK,GAAG,OAAO,KAAK,CAAC,MAAM,EAAE,QAAQ,SAAS,CAAC,KAAK;AAC3E,SAAO,SAAS,OAAO,wBAAwB,KAAK;AACtD;AAEO,IAAM,cAAc;AAAA,EACzB,SAAS,MAAM;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWf,cAAc,OAAwB;AACpC,WAAO,wBAAwB,KAAK,MAAM;AAAA,EAC5C;AAAA,EACA,SAAS,MAAc,IAAqB;AAC1C,WAAO,KAAK,cAAc,IAAI,KAAK,KAAK,cAAc,EAAE;AAAA,EAC1D;AACF;;;ACnCA,sBAA+B;AAExB,IAAM,sBAAsB;AAG5B,IAAM,wBAAwB;AAE9B,SAAS,4BAA4B,IAAa,KAAmD;AAC1G,MAAI,CAAC,GAAG,MAAM,WAAW,OAAO,EAAG,QAAO;AAC1C,QAAM,QAAQ,CAAC,MAAc,IAAI,IAAI,IAAI,CAAC;AAC1C,QAAM,UAAU,GAAG,UAAU,KAAK,CAAC,MAAO,EAAE,SAAS,yBAAyB,MAAM,EAAE,EAAE,KAAO,EAAE,OAAO,yBAAyB,MAAM,EAAE,IAAI,CAAE;AAC/I,MAAI,CAAC,QAAS,QAAO;AACrB,aAAO,kCAAiB,IAAI,KAAK;AAAA,IAC/B,UAAU;AAAA,IACV,UAAU;AAAA,IACV,MAAM;AAAA,IACN,cAAc;AAAA,IACd,UAAU;AAAA,EACZ,CAAC;AACH;;;AC9BA,IAAAA,eAA4B;AAC5B,IAAAC,uBAAwD;AAYxD,IAAM,oBAAoB;AAC1B,IAAM,eAAe;AAGrB,IAAM,gBAAgB;AAEtB,SAAS,aAAa,gBAAwB,aAAoC;AAChF,SAAO,GAAG,aAAa,GAAG,mBAAmB,cAAc,CAAC,IAAI,mBAAmB,eAAe,EAAE,CAAC;AACvG;AAEA,SAAS,aAAa,UAAkE;AACtF,MAAI;AACF,QAAI,CAAC,SAAS,WAAW,aAAa,EAAG,OAAM,IAAI,MAAM,wBAAwB;AACjF,UAAM,MAAM,SAAS,MAAM,cAAc,MAAM;AAC/C,UAAM,QAAQ,IAAI,MAAM,GAAG;AAC3B,QAAI,MAAM,WAAW,KAAK,CAAC,MAAM,CAAC,EAAG,OAAM,IAAI,MAAM,kBAAkB;AACvE,UAAM,iBAAiB,mBAAmB,MAAM,CAAC,CAAC;AAClD,UAAM,OAAO,mBAAmB,MAAM,CAAC,KAAK,EAAE;AAC9C,QAAI,CAAC,eAAgB,OAAM,IAAI,MAAM,uBAAuB;AAC5D,WAAO,EAAC,gBAAgB,GAAI,OAAO,EAAC,aAAa,KAAI,IAAI,CAAC,EAAE;AAAA,EAC9D,QAAQ;AACN,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AACF;AAEA,SAAS,YAAY,aAA8C;AACjE,QAAM,IAA4B,EAAC,gBAAgB,oBAAoB,QAAQ,mBAAkB;AACjG,QAAM,MAAM;AACZ,MAAI,IAAK,GAAE,gBAAgB,UAAU,GAAG;AACxC,SAAO;AACT;AAGA,SAAS,QAAQ,WAAoB,KAA8D;AACjG,SAAO,cAAc,UAAa,QAAQ,SAAY,CAAC,EAAC,WAAW,KAAK,IAAG,CAAC,IAAI;AAClF;AAMA,SAAS,cAAc,cAAsB,eAAuB,MAAe;AAIjF,SAAO,EAAC,aAAa,gBAAgB,YAAY,gBAAgB,UAAU,cAAa;AAC1F;AAGA,IAAM,cAAsC;AAAA,EAC1C,SAAS;AAAA,EACT,KAAK;AAAA;AAAA;AAAA;AAAA;AAAA,EAKL,QAAQ;AAAA,EACR,MAAM;AAAA;AAAA,EAEN,MAAM;AAAA;AAAA,EAEN,OAAO;AAAA,EACP,QAAQ;AACV;AAEA,SAAS,eAAe,OAAuB;AAC7C,SAAO,YAAY,MAAM,MAAM,GAAG,EAAE,CAAC,KAAK,EAAE,KAAK,YAAY;AAC/D;AAEA,SAAS,WAAW,SAAyB;AAC3C,SAAO,IAAI,KAAK,KAAK,IAAI,IAAI,UAAU,GAAM,EAAE,YAAY,EAAE,QAAQ,aAAa,GAAG;AACvF;AAOA,SAAS,YAAY,WAAmB,WAAkC;AACxE,QAAM,YAAQ,qCAAe,WAAW,SAAS;AACjD,MAAI,MAAO,QAAO,MAAM;AACxB,MAAI,cAAc,6BAAQ,SAAS,sBAAsB,KAAK,SAAS,GAAG;AACxE,WAAO,cAAc,UAAU,YAAY,CAAC;AAAA,EAC9C;AACA,SAAO;AACT;AAUA,SAAS,SAAS,OAA+B;AAC/C,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,IAAK,MAA0B;AACrC,SAAO,OAAO,MAAM,WAAW,IAAI;AACrC;AAaO,SAAS,oBAAoB,SAAoC,CAAC,GAAuB;AAC9F,WAAS,OAAO,OAAO,EAAC,GAAG,OAAM,CAAC;AAClC,QAAM,eAAe,IAAI,IAAI,OAAO,UAAU,iBAAiB;AAC/D,MAAI,aAAa,aAAa,YAAY,aAAa,aAAa,SAAS;AAC3E,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AACA,QAAM,UAAU,aAAa,SAAS,EAAE,QAAQ,OAAO,EAAE;AACzD,QAAM,eAAe,OAAO,iBAAiB;AAC7C,QAAM,SAAS,OAAO,WAAW;AACjC,MAAI,iBAAiB,OAAQ,OAAM,IAAI,MAAM,mEAAmE;AAChH,MAAI,iBAAiB,CAAC,OAAO,aAAc,KAAK,KAAK,CAAC,OAAO,UAAU,OAAO,MAAM,KAAK,OAAO,UAAW,KAAK,OAAO,SAAU,MAAS;AACxI,UAAM,IAAI,MAAM,8EAA8E;AAAA,EAChG;AACA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,kBAAkB;AAAA,IAClB,SAAS,MAAM,OAAO,WAAW;AAAA;AAAA;AAAA,IAIjC,eAAe,CAAC,UAAkB,YAAI,cAAc,KAAK;AAAA,IACzD,mBAAmB,CAAC,WAAmB,YAAoB,YAAI,SAAS,WAAW,OAAO;AAAA,IAC1F,cAAc,MAAa,IAAoB;AAG7C,UAAI,CAAC,YAAI,SAAS,KAAK,OAAO,GAAG,KAAK,EAAG,QAAO;AAKhD,YAAM,YAAQ,8BAAQ,KAAK,OAAO,KAAK,KAAK;AAC5C,aAAO,CAAC,KAAC,8BAAQ,KAAK,KAAK,KAAK,CAAC,CAAC,OAAO,WAAW,CAAC,CAAC,YAAY,GAAG,OAAO,GAAG,KAAK;AAAA,IACtF;AAAA,IAEA,MAAM,SAAS,QAAqB,QAA6C;AAI/E,YAAM,SAAS,CAAC,WAAyB;AACvC,cAAM,SAAS,GAAG,MAAM,SAAS,OAAO,QAAQ,KAAK,IAAI,OAAO,WAAW,KAAK,OAAO,SAAS,WAAW,OAAO,QAAQ;AAE1H,gBAAQ,KAAK,iCAA4B,OAAO,QAAQ,0BAA0B,GAAG,CAAC,EAAE;AACxF,eAAO,YAAY,MAAM;AACzB,eAAO;AAAA,MACT;AAIA,YAAM,SAAS,OAAO,mBAAmB,CAAC;AAC1C,YAAM,eAAe,wBAAwB,OAAO,aAAa,MAAM,KAAK,wBAAwB,OAAO,WAAW,MAAM;AAC5H,UAAI,aAAc,QAAO,OAAO,YAAY;AAC5C,YAAM,aAAS,8BAAQ,OAAO,aAAa,OAAO,WAAW;AAC7D,UAAI,CAAC,QAAQ,QAAS,QAAO,OAAO,wBAAwB,OAAO,WAAW,IAAI,OAAO,WAAW,EAAE;AACtG,YAAM,cAAc,YAAY,OAAO,WAAW,OAAO,SAAS;AAClE,UAAI,CAAC,YAAa,QAAO,OAAO,wBAAwB,OAAO,SAAS,IAAI,OAAO,SAAS,EAAE;AAC9F,YAAM,MAAM,OAAO,QAAQ;AAG3B,YAAM,SAAS,OAAO,kBAAkB,MAAM,eAAe,OAAO,WAAW,IAAI;AACnF,YAAM,OAAO,cAAc,OAAO,aAAa,QAAQ,GAAG;AAC1D,UAAI,CAAC,OAAO,CAAC,KAAK,SAAU,QAAO,OAAO,qCAAqC;AAE/E,YAAM,oBAAoB,WAAW,EAAE;AACvC,YAAM,OAAgC;AAAA,QACpC;AAAA;AAAA;AAAA,QAGA,UAAU,OAAO,OAAO,eAAe;AAAA,QACvC,mBAAmB,OAAO,eAAe;AAAA,QACzC,aAAa,OAAO;AAAA,QACpB,aAAa,KAAK;AAAA,QAClB,kBAAkB;AAAA,QAClB,QAAQ,OAAO;AAAA,QACf,UAAU,KAAK;AAAA,QACf,YAAY,KAAK;AAAA,QACjB,WAAW,OAAO;AAAA,QAClB,eAAe;AAAA,QACf,UAAU;AAAA,MACZ;AACA,YAAM,OAAO,QAAQ,OAAO,cAAc,OAAO,MAAM;AACvD,UAAI,KAAM,MAAK,UAAU;AAEzB,UAAI;AAQF,YAAI,MAAuB;AAC3B,YAAI,OAAsB,CAAC;AAC3B,iBAAS,UAAU,KAAK,WAAW;AACjC,cAAI;AACF,kBAAM,MAAM,MAAM,GAAG,OAAO,UAAU;AAAA,cACpC,QAAQ;AAAA,cACR,SAAS,YAAY,OAAO,GAAG;AAAA,cAC/B,MAAM,KAAK,UAAU,IAAI;AAAA,cACzB,QAAQ,cAAU,4BAAc,IAAM;AAAA,YACxC,CAAC;AACD,mBAAQ,MAAM,IAAI,KAAK,EAAE,MAAM,OAAO,CAAC,EAAE;AAAA,UAC3C,SAAS,KAAK;AACZ,gBAAI,WAAW,KAAK,QAAQ,QAAS,OAAM;AAC3C,kBAAM;AAAA,UACR;AACA,cAAI,KAAK,GAAI;AACb,gBAAM,QACJ,QAAQ,QACR,IAAI,UAAU,OACb,IAAI,WAAW,OAAO,gBAAgB,KAAK,OAAO,KAAK,WAAW,EAAE,CAAC;AACxE,cAAI,CAAC,SAAS,WAAW,KAAK,QAAQ,QAAS;AAC/C,gBAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,OAAO,UAAU,EAAE,CAAC;AAAA,QACzE;AACA,YAAI,CAAC,KAAK,GAAI,QAAO,OAAO,UAAU,KAAK,UAAU,eAAe,KAAK,OAAO,KAAK,WAAW,EAAE,EAAE,MAAM,GAAG,GAAG,CAAC,EAAE;AACnH,cAAM,IAAK,KAAK,SAAS,CAAC;AAE1B,cAAM,iBAAiB,OAAO,EAAE,mBAAmB,WAAW,EAAE,iBAAiB;AACjF,YAAI,CAAC,OAAO,CAAC,eAAgB,QAAO,OAAO,gDAAgD;AAC3F,cAAM,QAAQ,OAAO,WAAW,OAAO,EAAE,eAAe,GAAG,CAAC;AAC5D,cAAM,SAAS,OAAO,WAAW,OAAO,EAAE,gBAAgB,GAAG,CAAC;AAC9D,cAAM,iBAAiB,KAAK,MAAM,OAAO,EAAE,YAAY,EAAE,CAAC;AAC1D,YAAI,CAAC,QAAQ,CAAC,OAAO,SAAS,cAAc,KAAK,kBAAkB,KAAK,IAAI,GAAI,QAAO,OAAO,qBAAqB,OAAO,EAAE,QAAQ,CAAC,EAAE;AACvI,cAAM,WAAW,OAAO,SAAS,cAAc,KAAK,iBAAiB,KAAK,IAAI,IAC1E,KAAK,IAAI,gBAAgB,KAAK,IAAI,IAAI,YAAY,IAClD,KAAK,IAAI,IAAI;AAEjB,YAAI,EAAE,aAAa,UAAa,OAAO,EAAE,QAAQ,MAAM,OAAO,SAAU,QAAO,OAAO,sBAAsB,OAAO,EAAE,QAAQ,CAAC,OAAO,OAAO,QAAQ,GAAG;AAIvJ,YAAI,EAAE,iBAAiB,UAAa,EAAE,iBAAiB,KAAM,QAAO,OAAO,2BAA2B;AACtG,cAAM,gBAAgB,OAAO,EAAE,YAAY;AAC3C,YAAI,OAAO,iBAAiB,UAAa,OAAO,aAAa,IAAI,OAAO,OAAO,YAAY,EAAG,QAAO,OAAO,qBAAqB,aAAa,YAAY,OAAO,YAAY,GAAG;AAChL,cAAM,cACH,OAAO,EAAE,gBAAgB,YAAY,EAAE,eACvC,OAAO,EAAE,SAAS,YAAY,EAAE,QACjC;AACF,eAAO;AAAA,UACL,UAAU;AAAA,UACV,UAAU,iBAAiB,aAAa,gBAAgB,WAAW,IAAI,OAAO,OAAO,WAAW,CAAC;AAAA,UACjG;AAAA,UACA;AAAA,UACA,cAAc,OAAO;AAAA,UACrB,YAAY,OAAO,EAAE,aAAa,GAAG;AAAA,UACrC;AAAA,UACA,QAAQ,KAAK,IAAI,GAAG,QAAQ,MAAM;AAAA,UAClC,YAAY,OAAO,EAAE,gBAAgB,EAAE;AAAA,UACvC,aAAa;AAAA,UACb,cAAc;AAAA,QAChB;AAAA,MACF,SAAS,KAAK;AACZ,eAAO,OAAO,UAAU,eAAe,QAAQ,IAAI,QAAQ,MAAM,GAAG,GAAG,IAAI,OAAO,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC,EAAE;AAAA,MACxG;AAAA,IACF;AAAA,IAEA,MAAM,aAAa,OAAmC;AACpD,aAAO;AAAA,QACL,OAAO;AAAA,QACP,IAAI,MAAM;AAAA,QACV,OAAO,MAAM;AAAA,QACb,GAAI,MAAM,cAAc,EAAC,MAAM,MAAM,YAAW,IAAI,CAAC;AAAA,MACvD;AAAA,IACF;AAAA,IAEA,MAAM,cAAc,UAAkB,QAA+B;AACnE,YAAM,EAAC,eAAc,IAAI,aAAa,QAAQ;AAC9C,YAAM,MAAM,MAAM,MAAM,GAAG,OAAO,mBAAmB;AAAA,QACnD,QAAQ;AAAA,QACR,SAAS,YAAY,OAAO,GAAG;AAAA,QAC/B,MAAM,KAAK,UAAU,EAAC,gBAAgB,OAAM,CAAC;AAAA,QAC7C,YAAQ,4BAAc,IAAM;AAAA,MAC9B,CAAC;AACD,UAAI,CAAC,IAAI,GAAI,OAAM,IAAI,MAAM,8CAA8C,IAAI,MAAM,GAAG;AAAA,IAC1F;AAAA,IAEA,MAAM,YAAY,KAAuC;AACvD,YAAM,EAAC,gBAAgB,YAAW,IAAI,aAAa,IAAI,QAAQ;AAG/D,UAAI,IAAI,cAAc;AACpB,cAAM,KAAK,gBAAgB,IAAI,UAAU,IAAI,YAAY,EAAE,MAAM,MAAM;AAAA,QAAC,CAAC;AAAA,MAC3E;AACA,UAAI;AACF,cAAM,QAAQ,IAAI,gBAAgB,EAAC,eAAc,CAAC;AAClD,YAAI,YAAa,OAAM,IAAI,eAAe,WAAW;AACrD,cAAM,MAAM,MAAM;AAAA,UAChB,GAAG,OAAO,WAAW,MAAM,SAAS,CAAC;AAAA,UACrC,EAAC,SAAS,YAAY,OAAO,GAAG,GAAG,YAAQ,4BAAc,IAAM,EAAC;AAAA,QAClE;AACA,YAAI,CAAC,IAAI,GAAI,QAAO,EAAC,OAAO,UAAS;AACrC,cAAM,IAAK,MAAM,IAAI,KAAK;AAI1B,cAAM,MAA6C;AAAA,UACjD,iBAAiB;AAAA,UACjB,oBAAoB;AAAA,UACpB,YAAY;AAAA,UACZ,SAAS;AAAA,UACT,QAAQ;AAAA,UACR,UAAU;AAAA,QACZ;AACA,cAAM,QAAQ,IAAI,EAAE,UAAU,iBAAiB,KAAK;AACpD,cAAM,kBAAkB,EAAE,WAAW,gBAAgB,EAAE,WAAW;AAClE,cAAM,SAAS,SAAS,EAAE,aAAa,2BAA2B,CAAC,CAAC;AACpE,eAAO,EAAC,OAAO,iBAAiB,GAAI,SAAS,EAAC,YAAY,OAAM,IAAI,CAAC,EAAE;AAAA,MACzE,QAAQ;AACN,eAAO,EAAC,OAAO,UAAS;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AACF;;;AH5UO,IAAM,2BAAN,cAAuC,kCAAoB;AAAA,EAC7C;AAAA,EACnB,YAAY,SAAmC,QAAgC;AAC7E,UAAM,SAAS,MAAM;AACrB,SAAK,WAAW,oBAAoB,MAAM;AAAA,EAC5C;AAAA,EACmB,eAAe,OAAwB;AACxD,WAAO,YAAe,SAAS,OAAO,UAAU,KAAK,YAAe,SAAS,YAAY,KAAK;AAAA,EAChG;AAAA,EACmB,cAAc,WAAmB,SAA0B;AAC5E,WAAO,YAAe,SAAS,WAAW,OAAO;AAAA,EACnD;AACF;","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"]}
@@ -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 { Swap2Account, Swap2EngineConfig } from '@anywalletkit/protocol-swap2-core/swap2/base';
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
 
@@ -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 { Swap2Account, Swap2EngineConfig } from '@anywalletkit/protocol-swap2-core/swap2/base';
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
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  NearIntentsSwap2Protocol
3
- } from "./chunk-HUH3GOAM.js";
4
- import "./chunk-DA4EDMKN.js";
3
+ } from "./chunk-GKPYIWQ7.js";
4
+ import "./chunk-TCWV5CH4.js";
5
5
  import "./chunk-JBVOUD6Q.js";
6
6
  import "./chunk-P4T4UJWT.js";
7
7
  export {
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 {
@@ -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
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  nearIntentsProvider
3
- } from "./chunk-DA4EDMKN.js";
3
+ } from "./chunk-TCWV5CH4.js";
4
4
  import "./chunk-JBVOUD6Q.js";
5
5
  import "./chunk-P4T4UJWT.js";
6
6
  export {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@anywalletkit/protocol-swap2-near-intents",
3
- "version": "0.1.7",
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": ">=20"
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.5.0",
53
- "@anywalletkit/swap2-assets": "0.2.0"
52
+ "@anywalletkit/protocol-swap2-core": "0.6.1",
53
+ "@anywalletkit/swap2-assets": "0.2.2"
54
54
  },
55
55
  "peerDependencies": {
56
- "@anywalletkit/core": "0.5.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.2",
62
- "@anywalletkit/core": "0.5.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