Overview
NEAR Intents (also known as 1-Click ) is an intent-based cross-chain bridge that enables seamless asset transfers between StarkNet and 10+ blockchains including Solana, Ethereum, Base, Arbitrum, and NEAR.
Sable’s bridge feature uses NEAR 1-Click to support bi-directional transfers between StarkNet and external chains.
What is NEAR Intents?
NEAR Intents (1-Click) is a solver-based bridging protocol :
Intent-driven : Users express intent to swap/bridge, solvers fulfill it
No wrapped tokens : Direct native asset transfers
Fast settlement : Typically completes in 2-10 minutes
Multi-chain support : 15+ blockchains including EVM, Solana, NEAR, Bitcoin
Key Features
Bi-directional bridging : Bridge IN (external → StarkNet) or OUT (StarkNet → external)
Native assets : No synthetic tokens, receive actual STRK/SOL/ETH/etc.
Competitive rates : Solver competition ensures best prices
Simple UX : One deposit address, automatic execution
How Sable Integrates with NEAR Intents
Sable’s Bridge page (/bridge) uses 1-Click for all cross-chain transfers.
Bridge Architecture
┌──────────────────────────────────────────────────┐
│ BRIDGE IN FLOW │
│ (External Chain → StarkNet) │
├──────────────────────────────────────────────────┤
│ 1. User selects source chain + token │
│ 2. Sable fetches 1-Click quote │
│ 3. User gets deposit address │
│ 4. User sends funds to deposit address │
│ 5. 1-Click solver detects deposit │
│ 6. Solver swaps + bridges → STRK on StarkNet │
│ 7. STRK arrives at user's StarkNet wallet │
└──────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────┐
│ BRIDGE OUT FLOW │
│ (StarkNet → External Chain) │
├──────────────────────────────────────────────────┤
│ 1. User selects destination chain + token │
│ 2. Sable fetches 1-Click quote │
│ 3. User approves STRK to 1-Click deposit address │
│ 4. Sable executes STRK transfer │
│ 5. 1-Click solver detects deposit │
│ 6. Solver swaps + bridges → target token │
│ 7. Target token arrives at destination wallet │
└──────────────────────────────────────────────────┘
Supported Chains
NEAR 1-Click supports bridging to/from 15+ blockchains :
Solana Native SOL and SPL tokens
Ethereum ETH and ERC-20 tokens
Arbitrum Arbitrum One and Arbitrum Nova
Bitcoin BTC (via wrapped assets)
StarkNet is always one side of the bridge. You bridge to or from StarkNet, not between two external chains.
API Integration
Sable integrates with the 1-Click REST API for quotes, execution, and status tracking.
Base URL
https://1click.chaindefuser.com
Fetch Available Tokens
// From: ~/workspace/source/src/lib/api/oneclick.ts
import { fetchOneClickTokens , getAvailableChains } from "@/lib/api/oneclick" ;
// Fetch all supported tokens
const tokens = await fetchOneClickTokens ();
// Get list of chains (excluding StarkNet)
const chains = getAvailableChains ( tokens );
console . log ( chains );
// [
// { id: "sol", name: "Solana", tokenCount: 45 },
// { id: "eth", name: "Ethereum", tokenCount: 120 },
// { id: "base", name: "Base", tokenCount: 38 },
// { id: "arb", name: "Arbitrum", tokenCount: 67 },
// ...
// ]
// Get tokens for a specific chain
const solTokens = tokens . filter ( t => t . blockchain === "solana" );
console . log ( solTokens [ 0 ]);
// {
// assetId: "nep141:sol.omft.near",
// decimals: 9,
// blockchain: "solana",
// symbol: "SOL",
// price: 150.23,
// contractAddress: "So11111111111111111111111111111111111111112",
// }
Get Bridge Quote
import { getOneClickQuote , STRK_ASSET_ID , makeDeadline } from "@/lib/api/oneclick" ;
// Bridge OUT: 100 STRK → SOL
const quote = await getOneClickQuote ({
dry: false , // false = get real deposit address
swapType: "EXACT_INPUT" ,
slippageTolerance: 100 , // 1% (in basis points)
originAsset: STRK_ASSET_ID , // STRK on StarkNet
depositType: "ORIGIN_CHAIN" ,
destinationAsset: "nep141:sol.omft.near" , // SOL
amount: "100000000000000000000" , // 100 STRK (18 decimals)
refundTo: userStarknetAddress ,
refundType: "ORIGIN_CHAIN" ,
recipient: userSolanaAddress , // User's Solana wallet
recipientType: "DESTINATION_CHAIN" ,
deadline: makeDeadline (), // 24 hours from now
});
console . log ( quote );
// {
// quote: {
// amountIn: "100000000000000000000",
// amountInFormatted: "100",
// amountOut: "0.65 SOL",
// amountOutFormatted: "0.65",
// timeEstimate: 300, // 5 minutes
// depositAddress: "0x1234...abcd", // Send STRK here
// },
// depositAddress: "0x1234...abcd",
// }
Execute Bridge Transaction
import { Contract } from "starknet" ;
const STRK_ADDRESS = "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d" ;
// Approve STRK to 1-Click deposit address
const strkContract = new Contract ( ERC20_ABI , STRK_ADDRESS , account );
await strkContract . approve ( quote . depositAddress , amount );
// Transfer STRK to deposit address
await strkContract . transfer ( quote . depositAddress , amount );
// 1-Click solver will detect the deposit and fulfill the intent
Track Bridge Status
import { getOneClickStatus } from "@/lib/api/oneclick" ;
// Poll status every 10 seconds
const interval = setInterval ( async () => {
const status = await getOneClickStatus ( quote . depositAddress );
console . log ( status . status );
// "PENDING_DEPOSIT" → "KNOWN_DEPOSIT_TX" → "PROCESSING" → "SUCCESS"
if ( status . status === "SUCCESS" || status . status === "COMPLETED" ) {
clearInterval ( interval );
console . log ( "Bridge complete!" );
console . log ( "Destination TX:" , status . swapDetails ?. destinationChainTxHashes );
}
}, 10_000 );
Status Flow
Bridge transactions progress through multiple states:
┌───────────────────┐
│ PENDING_DEPOSIT │ Waiting for user to send funds
└─────────┬──────────┘
│
▼
┌─────────┼──────────┐
│ KNOWN_DEPOSIT_TX │ Deposit detected on-chain
└─────────┬──────────┘
│
▼
┌─────────┼──────────┐
│ PROCESSING │ Solver executing swap + bridge
└─────────┬──────────┘
│
▼
┌─────────┼──────────┐
│ SUCCESS │ Funds arrived at destination
└─────────┴──────────┘
Other possible states :
FAILED: Transaction failed (user receives refund)
REFUNDED: Funds returned to refund address
INCOMPLETE_DEPOSIT: User sent wrong amount
STRK Asset ID
All StarkNet bridging operations use the STRK asset ID :
nep141:starknet.omft.near
This is the 1-Click identifier for STRK on StarkNet.
Which Sable Features Use NEAR Intents?
Bridge Page Bi-Directional Cross-Chain Bridge
Bridge IN: External chain → STRK on StarkNet
Bridge OUT: STRK on StarkNet → External chain
Supported chains: Solana, Ethereum, Base, Arbitrum, NEAR, Polygon, Avalanche, Optimism, etc.
UI: /bridge
Status tracking: Real-time progress updates
Frontend Integration
Sable’s bridge page provides a user-friendly interface for cross-chain transfers.
// From: ~/workspace/source/src/hooks/use-bridge.ts
import { getOneClickQuote , getOneClickStatus } from "@/lib/api/oneclick" ;
async function executeBridge (
direction : "in" | "out" ,
sourceChain : string ,
sourceToken : string ,
destinationChain : string ,
destinationToken : string ,
amount : string ,
userAddress : string ,
) {
// 1. Get quote
const quote = await getOneClickQuote ({
dry: false ,
swapType: "EXACT_INPUT" ,
slippageTolerance: 100 ,
originAsset: sourceToken ,
depositType: "ORIGIN_CHAIN" ,
destinationAsset: destinationToken ,
amount ,
refundTo: userAddress ,
refundType: "ORIGIN_CHAIN" ,
recipient: userAddress ,
recipientType: "DESTINATION_CHAIN" ,
deadline: makeDeadline (),
});
// 2. Display deposit address to user
console . log ( `Send ${ quote . quote . amountInFormatted } to ${ quote . depositAddress } ` );
// 3. If bridge OUT, execute STRK transfer
if ( direction === "out" ) {
await strkContract . transfer ( quote . depositAddress , amount );
}
// 4. Poll status
const interval = setInterval ( async () => {
const status = await getOneClickStatus ( quote . depositAddress );
updateUI ( status );
if ( status . status === "SUCCESS" ) {
clearInterval ( interval );
showSuccessMessage ();
}
}, 10_000 );
}
Error Handling
1-Click API returns user-friendly error messages:
try {
const quote = await getOneClickQuote ( params );
} catch ( error ) {
if ( error . message . includes ( "try at least" )) {
// Amount too low for bridge
alert ( "Amount too low. Minimum ~10 STRK required." );
} else if ( error . message . includes ( "timeout" )) {
// Solvers couldn't fulfill in time
alert ( "Bridge quote timed out. Please try again." );
} else if ( error . message . includes ( "not valid" )) {
// Invalid address format
alert ( "Invalid destination address for selected chain." );
}
}
External Resources
NEAR 1-Click Documentation Official 1-Click protocol documentation
NEAR Intents Learn more about NEAR’s intent-based architecture
1-Click API Reference REST API for quotes and status tracking
Integration Source Code :
API integration: ~/workspace/source/src/lib/api/oneclick.ts
Bridge UI: ~/workspace/source/src/app/bridge/page.tsx
Bridge hooks: ~/workspace/source/src/hooks/use-bridge.ts