Resolvers के लिए

Aqua लिक्विडिटी के विरुद्ध स्वैप भरें: resolver की भूमिका के लिए क्या चाहिए, ऑन-चेन fill कैसे काम करता है और SwapVM SDK से उसे कोट करके कैसे निष्पादित करें।

10 मिनट में पढ़ेंअपडेट किया गया जुलाई 2026

Aqua में resolvers क्या करते हैं

पूरे 1inch Network में, Aqua लिक्विडिटी भरने वाले स्वैप 1inch Resolvers रूट करते हैं: मार्केट मेकर और आर्बिट्राज ट्रेडर, जो 1inch की सत्यापन प्रक्रिया पूरी करते हैं।

Aqua स्वयं न discovery करता है और न matching। यह हर स्वैप कॉल पर एक पोज़िशन को एक काउंटरपार्टी के विरुद्ध कीमत देकर निष्पादित करता है। कौन-सी पोज़िशन, किस आकार में भरनी है, यह resolver का काम है: 1inch रूटिंग नेटवर्क को स्वैप सौंपती है, और आपके अपने सिस्टम कॉन्ट्रैक्ट्स को सीधे कॉल कर सकते हैं।

बुनियादी मैकेनिक्स में नए हैं? शुरुआत करें Aqua कैसे काम करता है से।

शुरू करने से पहले

  • 1inch Business पोर्टल के ज़रिए resolver सत्यापन, जो प्रति-चेन एक्सेस टोकन देता है
  • स्वैप ट्रांज़ैक्शन भेजने वाली ऑपरेटर EOA पर एक्सेस टोकन
  • लक्ष्य चेन पर नोड एक्सेस, साथ ही fills के लिए इनपुट टोकन और गैस
  • कैनोनिकल कॉन्ट्रैक्ट पते, हर समर्थित चेन पर एक जैसे और नीचे सूचीबद्ध
  • Aqua API डिस्कवरी पथ के लिए Business portal से एक API कुंजी

कॉन्ट्रैक्ट पते

Aqua और SwapVM राउटर निर्धारक (deterministic) डिप्लॉयमेंट हैं, हर समर्थित चेन पर एक ही पता। केवल इन्हीं दो कॉन्ट्रैक्ट से इंटरैक्ट करें। बाकी कुछ भी Aqua नहीं है।

Aqua (रजिस्ट्री)
0x1111113ccf1426a8e30e2bff5e005d929bf6a90a
SwapVM राउटर
0x111111338c5091e8440b67b168bae16a668ac0de

Fill कैसे काम करता है

  1. 1

    सत्यापित हों

    Business पोर्टल से resolver ऑनबोर्डिंग पूरी करें और हर उस चेन के लिए एक्सेस टोकन प्राप्त करें जिस पर आप fill करते हैं।

  2. 2

    पोज़िशन खोजें

    Aqua API से खुली पोजीशनें लें, Shipped और Docked इवेंट्स से लाइव सेट फिर बनाएं, या नेटवर्क रिज़ॉल्वर के रूप में 1inch रूटिंग से स्वैप प्राप्त करें।

  3. 3

    भेजने से ठीक पहले कोट करें

    डिकोड की गई ऑर्डर के साथ राउटर का quote फ़ंक्शन static call से कॉल करें। कोट लाइव वॉलेट बैकिंग पढ़ते हैं, इसलिए दूसरे fills आते ही बदल जाते हैं।

  4. 4

    अपनी सीमाएँ तय करें

    ताज़ा कोट से न्यूनतम आउटपुट निकालें और छोटी deadline रखें। तब खिसकी हुई कर्व खराब दर पर भरने के बजाय revert कर देती है।

  5. 5

    स्वैप करें और सत्यापित करें

    एक्सेस टोकन रखने वाली EOA से स्वैप भेजें, सफल रसीद की मांग करें और निष्पादित राशियाँ Swapped इवेंट से पढ़ें।

Quickstart: एक पोज़िशन कोट करें और भरें

नीचे के उदाहरण Aqua API से एक खुली पोजीशन खोजते हैं, उसका कोट लेते हैं और संरक्षित फिल भेजते हैं। ये Node 22 पर TypeScript SDKs के साथ चलते हैं। कॉन्ट्रैक्ट, इवेंट, SDKs और API पोजीशन को strategy कहते हैं, इसलिए कोड भी यही कहता है।

SDK इंस्टॉल करेंbash
pnpm add @1inch/aqua-sdk @1inch/swap-vm-sdk viem
Aqua API से खुली पोजीशनें खोजेंtypescript
import assert from 'node:assert'
import { HexString, Order } from '@1inch/swap-vm-sdk'

// Every currently open position from every LP, newest first. Auth is the
// same API key the other 1inch APIs use - issued in the Business portal.
const response = await fetch('https://api.1inch.com/aqua/v1.0/strategies/opened?chainIds=1&limit=50', {
  headers: { Authorization: `Bearer ${process.env.ONEINCH_API_KEY}` },
})
assert(response.ok, `Aqua API responded ${response.status}`)
const { items, nextCursor } = await response.json()

// Pick by your own criteria. Per-token balance and allowance in each item are
// useful pre-filters, but they are indexed with a delay - only a fresh
// on-chain quote() is authoritative.
const strategy = items[0]
const order = Order.decode(new HexString(strategy.strategyBytes))
console.log('candidate:', strategy.strategyHash, 'tokens:', strategy.tokens.length, 'more:', nextCursor !== null)
कोट, fill और सत्यापनtypescript
import assert from 'node:assert'
import { ABI, Address, HexString, Order, SwappedEvent, SwapVMContract, TakerTraits } from '@1inch/swap-vm-sdk'
import { createPublicClient, createWalletClient, decodeFunctionResult, erc20Abi, http, isHex } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
import { mainnet } from 'viem/chains'

// The SwapVM router is a deterministic deployment - the same address on every
// supported chain (see the contract addresses above). The strategy bytes come
// from the Aqua API or a Shipped event. The operator key belongs to the EOA
// holding the resolver credential - it must be the transaction origin.
const router = new Address('0x111111338c5091e8440b67b168bae16a668ac0de')
const strategyBytes = process.env.STRATEGY_BYTES
const operatorPrivateKey = process.env.OPERATOR_PRIVATE_KEY
assert(isHex(strategyBytes) && isHex(operatorPrivateKey))

const order = Order.decode(new HexString(strategyBytes))

const USDC = new Address('0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48')
const WETH = new Address('0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2')
const amountIn = 3_000n * 10n ** 6n

const operator = privateKeyToAccount(operatorPrivateKey)
const publicClient = createPublicClient({ chain: mainnet, transport: http() })
const wallet = createWalletClient({ chain: mainnet, transport: http(), account: operator })

// 1. Preview the swap with a static quote() call, right before you submit.
const quoteTx = SwapVMContract.buildQuoteTx(router, {
  order,
  tokenIn: USDC,
  tokenOut: WETH,
  amount: amountIn,
  takerTraits: TakerTraits.new({ exactIn: true }),
})
const quoted = await publicClient.call({ to: quoteTx.to, data: quoteTx.data })
assert(quoted.data, 'quote call returned no data')
const [, quotedOut] = decodeFunctionResult({ abi: ABI.SWAP_VM_ABI, functionName: 'quote', data: quoted.data })
console.log('quoted output:', quotedOut)

// 2. Approve the router to move the input token (once per token and chain).
const approveHash = await wallet.writeContract({
  address: USDC.toString(),
  abi: erc20Abi,
  functionName: 'approve',
  args: [router.toString(), amountIn],
})
await publicClient.waitForTransactionReceipt({ hash: approveHash })

// 3. Swap with a minimum-output floor and a short deadline. Balances and
// curves move between quote and fill - never submit unprotected traits.
const swapTx = SwapVMContract.buildSwapTx(router, {
  order,
  tokenIn: USDC,
  tokenOut: WETH,
  amount: amountIn,
  takerTraits: TakerTraits.new({
    exactIn: true,
    threshold: (quotedOut * 995n) / 1_000n,
    deadline: BigInt(Math.floor(Date.now() / 1_000) + 60),
  }),
})
const fillHash = await wallet.sendTransaction(swapTx)
const receipt = await publicClient.waitForTransactionReceipt({ hash: fillHash })
assert(receipt.status === 'success', 'fill reverted')

// 4. Verify the executed amounts from the router's Swapped event.
const swappedLog = receipt.logs.find((log) => log.topics[0] === SwappedEvent.TOPIC.toString())
assert(swappedLog, 'no Swapped event in the receipt')
const swapped = SwappedEvent.fromLog(swappedLog)
console.log('filled:', swapped.amountIn, '->', swapped.amountOut)

पहले फोर्क पर पूरा चक्र आज़माएं

ऊपर का सब कुछ लोकल फोर्क पर सुरक्षित रूप से आज़माया जा सकता है। Foundry का anvil किसी ब्लॉक पर चेन की प्रति बनाता है, यानी असली कॉन्ट्रैक्ट और असली लाइव पोजीशनें, दांव पर कुछ भी नहीं। बिना कुंजी के सेंड सक्षम होने पर आप किसी भी ऐसी EOA की तरह काम कर सकते हैं जिसके पास पहले से एक्सेस टोकन है, और अपनी पहली असली ट्रांज़ैक्शन से पहले पूरा चक्र चला सकते हैं: खोजें, कोट लें, भरें, सत्यापित करें।

मेननेट फोर्क पर ड्राई-रनbash
# Real Aqua bytecode and live positions at the forked block, zero real spend
anvil --fork-url $YOUR_RPC_URL --auto-impersonate

# Point the quickstart at http://127.0.0.1:8545 and send from any EOA that
# already holds the per-chain access token - no key needed on a fork

ऑन-चेन फिल कैसे निष्पादित होता है

फिल SwapVM राउटर को भेजी गई एक ही ट्रांज़ैक्शन है। राउटर पोजीशन का निर्देश प्रोग्राम चलाता है: पहले एक्सेस जांच, फिर मूल्य वक्र, फिर टोकन की आवाजाही। इनपुट टोकन उसी ट्रांज़ैक्शन में आपकी EOA से LP के वॉलेट में जाता है और आउटपुट टोकन आपके पास लौटता है, जबकि Aqua रजिस्ट्री पोजीशन के बैलेंस अपडेट कर Pushed और Pulled उत्सर्जित करती है। किसी भी क्षण कुछ भी पूल में नहीं रहता।

सब कुछ पूर्ण या शून्य है। निष्पादन के समय कोई जांच विफल हो, एक्सेस टोकन गायब, threshold पूरा नहीं, deadline बीत गई या वॉलेट बैकिंग कम, तो पूरी ट्रांज़ैक्शन revert होती है और कोई टोकन नहीं हिलता। revert हुए फिल की लागत केवल गैस है।

राउटर quote और swap देता है, और दोनों एक ही मूल्य पथ चलाते हैं। कोई भी view फ़ंक्शन नहीं है, इसलिए quote को eth_call से स्टैटिक कॉल की तरह बुलाएं: यह लाइव स्थिति पढ़ता है, आपके दिए स्वैप की सटीक कीमत निकालता है और कुछ नहीं बदलता। वह पूर्वावलोकन कोई वचन नहीं है। केवल swap के साथ भेजे traits ही निष्पादन को बांधते हैं।

TakerTraits आपकी निष्पादन सीमाएं ट्रांज़ैक्शन में ले जाते हैं। इन्हें चेन लागू करती है, SDK नहीं। सबसे अधिक काम आने वाले:

exactIn
कौन-सा पक्ष तय है। सटीक इनपुट में आप भेजी राशि तय करते हैं और प्राप्ति को सीमित करते हैं। सटीक आउटपुट में प्राप्ति तय होती है और भेजी राशि सीमित।
threshold
स्वयं सीमा। सटीक इनपुट पर वह न्यूनतम आउटपुट जो फिल को देना ही होगा। सटीक आउटपुट पर आपके खर्च की अधिकतम सीमा। शून्य threshold जांच बंद कर देता है, इसलिए इसे हमेशा ताज़ा कोट से निकालें।
deadline
unix-सेकंड में समाप्ति। उसके बाद माइन हुई ट्रांज़ैक्शन revert होती है, इसलिए mempool में अटका फिल पुरानी कर्व पर निष्पादित नहीं हो सकता।
customReceiver
आउटपुट भेजने वाली EOA के बजाय किसी और पते पर देता है, जैसे कोई ट्रेज़री पता। एक्सेस जांच फिर भी ट्रांज़ैक्शन मूल पर ही चलती है।
shouldUnwrap
जब आउटपुट रैप्ड नेटिव टोकन हो तो रैप्ड रूप की जगह नेटिव टोकन प्राप्त करें।

परिणाम के लिए अपने गणित पर भरोसा न करें। सफल रसीद की मांग करें, फिर राउटर का Swapped इवेंट डिकोड करें: orderHash, maker, taker, tokenIn, tokenOut, amountIn और amountOut। यही निष्पादित राशियां हैं, और आपकी बहीखाता प्रविष्टियों में यही दर्ज होनी चाहिए।

संभालने योग्य विफलता स्थितियाँ

बंद पोज़िशन
LP कभी भी पोजीशन बंद कर सकता है, और उसके जाते ही बैलेंस रीड revert होते हैं। API की opened सूची से गायब पोजीशन बंद है, लेकिन दो पोल के बीच ऑन-चेन revert ही सच का स्रोत रहता है। हर फिल से पहले दोबारा जांचें।
कम वॉलेट बैकिंग
पोजीशनें साझा वॉलेट बैलेंस से कोट करती हैं। कोई प्रतिस्पर्धी फिल उसे पहले खाली कर सकता है, जिससे आपका ट्रांसफर revert हो जाता है भले ही कोट सही दिखा हो। API के balance और allowance फ़ील्ड प्री-फ़िल्टर में मदद करते हैं, पर वे देरी से इंडेक्स होते हैं। केवल ताज़ा ऑन-चेन कोट ही आधिकारिक है।
खिसका हुआ भाव
Fills आने और समय बीतने के साथ कोट बासी हो जाते हैं। न्यूनतम-आउटपुट सीमा और deadline खराब fill को साफ़ revert में बदल देते हैं।
एक्सेस टोकन अनुपस्थित
ट्रांज़ैक्शन ओरिजिन पर क्रेडेंशियल न हो तो dApp में बनी पोज़िशनें प्राइसिंग चलने से पहले ही स्वैप revert कर देती हैं।
गैर-कैनोनिकल पते
ऊपर दिए दो कैनोनिकल पते ही Aqua हैं। कहीं और भेजे गए फिल लाइव पोजीशनों तक नहीं पहुंचते। प्रति चेन सत्यापित करने को कुछ नहीं है, डिप्लॉयमेंट हर जगह एक जैसे हैं।

प्रोडक्शन में संचालन

ऑपरेटर EOA को केवल वॉलेट नहीं, क्रेडेंशियल मानें। उसके पास प्रति-चेन एक्सेस टोकन है, इसलिए उसकी कुंजी को समर्पित साइनर में अलग रखें, पते पर केवल कार्यशील इन्वेंटरी और गैस रखें, और उसे किसी और काम में न लगाएं।

गैस अनुमान को अपना आखिरी द्वार बनने दें। वॉलेट लाइब्रेरियां प्रसारण से पहले गैस का अनुमान लगाती हैं, और असफल अनुमान वही revert है जो कुछ भी भेजे जाने से पहले सामने आ जाता है। इसे छोड़ा गया फिल मानें और आंख मूंदकर दोहराने के बजाय अगले उम्मीदवार पर बढ़ें।

तीन संकेतों पर नज़र रखें। आपकी revert दर, जो खोज डेटा पुराना होने या आकार बैकिंग के बहुत करीब होने पर बढ़ती है। हर फिल के पीछे कोट की उम्र, जो सेकंडों में रहनी चाहिए। और Swapped से निष्पादित राशियां बनाम आपकी कोट, जो बहाव को नुकसान से पहले पकड़ लेती है।

प्रोडक्शन में पोज़िशनें खोजना

लाइव सेट पाने के दो रास्ते हैं। Aqua API सबसे तेज़ शुरुआत है। इवेंट्स से पुनर्निर्माण ट्रस्टलेस है और कोई बाहरी निर्भरता नहीं जोड़ता। दोनों एक ही कोट-और-फिल फ्लो में जाते हैं।

Aqua API हर LP की सभी वर्तमान में खुली पोजीशनें सूचीबद्ध करती है: api.1inch.com/aqua पर GET /v1.0/strategies/opened, कर्सर पेजिनेशन (प्रति पेज 500 तक) और चेन व app फ़िल्टर के साथ। हर आइटम में वे strategyBytes होते हैं जो आप Order.decode को देते हैं, साथ ही उम्मीदवारों की प्री-फ़िल्टरिंग के लिए प्रति-टोकन balance और allowance। अनुरोधों को वही API कुंजी चाहिए जो अन्य 1inch APIs उपयोग करती हैं, जो Business portal में जारी होती है। इंडेक्स चेन से थोड़ा पीछे रहता है, इसलिए फिल से पहले हमेशा ऑन-चेन ताज़ा कोट लें।

Aqua रजिस्ट्री, यानी प्रोटोकॉल का मुख्य कॉन्ट्रैक्ट, पोज़िशन खुलने पर Shipped और बंद होने पर Docked इवेंट देती है। लाइव सेट = Shipped घटा Docked, जो हर चेन के डिप्लॉयमेंट ब्लॉक से लॉग पढ़कर बनाया जाता है। इवेंट फ़ील्ड topics के बजाय लॉग डेटा में होते हैं: कॉन्ट्रैक्ट पते और इवेंट सिग्नेचर से फ़िल्टर करें, फिर क्लाइंट-साइड डिकोड और मैच करें।

इवेंट के स्वरूप छोटे हैं। Shipped में maker, app, strategyHash और पूरी strategy bytes होती हैं। Docked में maker, app और strategyHash। SDK दोनों के लिए टाइप्ड सहायक देता है, ShippedEvent और DockedEvent, fromLog डिकोडर और TOPIC स्थिरांकों सहित, इसलिए आप कभी ABI हाथ से नहीं लिखते।

इवेंट्स से लाइव सेट फिर बनाएंtypescript
import { DockedEvent, ShippedEvent } from '@1inch/aqua-sdk'
import { createPublicClient, http } from 'viem'
import { mainnet } from 'viem/chains'

const AQUA = '0x1111113ccf1426a8e30e2bff5e005d929bf6a90a'
const publicClient = createPublicClient({ chain: mainnet, transport: http() })

// Shipped and Docked carry every field in the log data, none in topics, so
// pull the registry's logs and match on the event signature client-side.
const logs = await publicClient.getLogs({
  address: AQUA,
  fromBlock: 23_000_000n, // the per-chain deployment block, or your last checkpoint
  toBlock: 'latest',
})

const live = new Map<string, ShippedEvent>()
for (const log of logs) {
  if (log.topics[0] === ShippedEvent.TOPIC.toString()) {
    const shipped = ShippedEvent.fromLog(log)
    live.set(shipped.strategyHash.toString(), shipped)
  } else if (log.topics[0] === DockedEvent.TOPIC.toString()) {
    live.delete(DockedEvent.fromLog(log).strategyHash.toString())
  }
}

// live now maps strategyHash -> Shipped payload: maker, app and the strategy
// bytes you decode with Order.decode before quoting.
console.log('open positions:', live.size)

बाकी ऑन-चेन रीड से मिलता है। रजिस्ट्री के rawBalances और safeBalances व्यू पोजीशन के पीछे की वॉलेट बैकिंग बताते हैं, और राउटर के Swapped इवेंट निष्पादित स्वैप दर्ज करते हैं। कोट कैश करने के बजाय ताज़ा रखें।

फिल का आकार बैकिंग से शुरू होता है, कोट से नहीं। रजिस्ट्री व्यू से पोजीशन की बैकिंग पढ़ें, अपना आकार उससे काफी नीचे रखें, फिर भेजने से ठीक पहले उसी सटीक आकार का ताज़ा कोट लें। API के balance और allowance फ़ील्ड कई उम्मीदवारों पर सस्ता पहला फ़िल्टर हैं, एक के लिए व्यू और कोट ही सच हैं।

रिज़ॉल्वर FAQ

नहीं। एक्सेस जांच मांगती है कि ट्रांज़ैक्शन का मूल वही EOA हो जिसके पास एक्सेस टोकन है, इसलिए कॉन्ट्रैक्ट वॉलेट और बंडलर इसे पार नहीं कर सकते। फिल सत्यापित ऑपरेटर EOA से भेजें।

नहीं। quote फ़ंक्शन लाइव स्थिति का स्टैटिक पूर्वावलोकन है और कुछ नहीं हिलाता। केवल swap के साथ भेजे गए TakerTraits निष्पादन को बांधते हैं: threshold और deadline ऑन-चेन लागू होते हैं।

सिर्फ गैस। कोई भी असफल जांच पूरी ट्रांज़ैक्शन revert कर देती है, इसलिए किसी भी ओर टोकन नहीं हिलते।

1inch Business portal से सत्यापन प्रति-चेन एक्सेस टोकन देता है। जिस भी चेन पर आप भरते हैं, ऑपरेटर EOA के पास वह टोकन होना चाहिए।

Aqua API संदर्भ पोजीशन खोज और आंकड़ों के लिए एंडपॉइंट, पैरामीटर और रिस्पॉन्स स्वरूप, Business portal में। Aqua SDK और SwapVM SDK Fill फ़्लो के लिए टाइप्ड बिल्डर, डिकोडर और इवेंट पार्सर, 1inch/sdks रिपो में। Resolver ऑनबोर्डिंग 1inch Business पोर्टल पर सत्यापन चरण और resolver दस्तावेज़। Aqua व्हाइटपेपर साझा लिक्विडिटी परत का पूरा डिज़ाइन।

Aqua लिक्विडिटी भरने के लिए तैयार?

सत्यापन शुरू करें और 1inch Business पोर्टल के ज़रिए टीम से संपर्क करें।

Business पोर्टल खोलें