API
हर OpenFiat नोड एक JSON-RPC 2.0 एंडपॉइंट उजागर करता है जो सीधे Solana के अपने
JSON-RPC API पर आधारित है — एक REST संसाधन पदानुक्रम के बजाय एक ही POST
एंडपॉइंट पर getX/sendX जैसे camelCase मेथड नाम। इसे
openfiat-core में rpc और api
crate लागू करते हैं।
एंडपॉइंट
POST /rpc
Content-Type: application/json
हर अनुरोध एक मानक JSON-RPC 2.0 आवरण होता है:
{ "jsonrpc": "2.0", "id": 1, "method": "getAdvertisement", "params": { "id": "ad-1" } }
और हर प्रतिक्रिया या तो एक result होती है या एक error, कभी दोनों नहीं:
{ "jsonrpc": "2.0", "id": 1, "result": { "id": "ad-1", "status": "Active", "..." : "..." } }
सार्वजनिक devnet नोड https://openfiat.allenhark.com पर है — वही होस्ट
नोड्स के लिए एक एंट्रीपॉइंट multiaddr भी प्रकाशित करता है, जो एक भिन्न काम के लिए
एक भिन्न पता है (देखें
getting started)।
आप जो भी नोड स्वयं चलाते हैं वह :7080 पर वही इंटरफ़ेस परोसता है।
कुंजियाँ, peer id और हस्ताक्षर base58 हैं
हर सार्वजनिक कुंजी, peer पहचानकर्ता, हस्ताक्षर और इवेंट पहचानकर्ता एक base58 स्ट्रिंग है:
{
"service_id": "node-ALLENLMtV1zEAHT3xpVryqcbdPCB8c9JhM1Jdbe5XHg5",
"provider": "12D3KooWK9hQ7TwbfvFiaAxUbRFCkdhS7iEpAJDnewNL1anyREQ1",
"provider_public_key": "ALLENLMtV1zEAHT3xpVryqcbdPCB8c9JhM1Jdbe5XHg5"
}
हाल तक ये पूर्णांकों के arrays थे। यदि आप
"provider_public_key": [192, 74, 15, ...] देखते हैं, तो आप एक ऐसे नोड से बात कर रहे हैं
जो इस बदलाव से पुराना है — और उस प्रतिक्रिया में कुछ भी एक प्रकाशित
सार्वजनिक कुंजी को एक लीक हुई निजी कुंजी से अलग नहीं करता, क्योंकि एक Ed25519 गुप्त
भी बत्तीस बाइट का होता है। वही अस्पष्टता इसके बदलने का कारण है। base58
रूप एकमात्र उपयोग-योग्य भी है: 12D3KooW… वही है जो एक --entrypoint लेता है
और जिसे एक लॉग में खोजा जा सकता है।
यह केवल एक प्रदर्शन बदलाव नहीं है। एक sendX payload अपने आंतरिक struct के JSON पर
हस्ताक्षरित होता है, इसलिए एक क्लाइंट जो एक कुंजी को एक array के रूप में payload में लिखता है, एक
ऐसी प्रतिलिपि उत्पन्न करता है जिसे नोड पुनरुत्पन्न नहीं करता। तब हस्ताक्षर
सत्यापित होने में विफल रहता है — जो एक अस्वीकृत परिवर्तन के रूप में सामने आता है, न कि
एक पार्स त्रुटि के रूप में। एक SDK का उपयोग करें और यह आपके लिए संभाल लिया जाता है;
वायर फ़ॉर्मैट को हाथ से गढ़ें, तो पहचानकर्ताओं को base58 के रूप में एन्कोड करें।
बाइट फ़ील्ड जो पहचानकर्ता नहीं हैं वे arrays बने रहते हैं। एक विवाद मत का
commitment और उसका रिवील secret अपारदर्शी बत्तीस-बाइट मान हैं,
पहचान नहीं, और arrays के रूप में भेजे जाते हैं। अंतर इस पर है कि फ़ील्ड क्या है,
न कि उसकी लंबाई पर।
मेथड नामकरण
पठन मेथड get से शुरू होते हैं और कभी स्थिति नहीं बदलते:
{ "method": "getReservation", "params": { "id": "res-1" } }
{ "method": "getReservations", "params": {} }
एक getMyX मेथड फिर भी एक पठन है, पर वह केवल उस वॉलेट के लिए उत्तर देता है जिसे
कॉलर धारण करना सिद्ध करता है — देखें वॉलेट-प्रूफ पठन।
परिवर्तन send से शुरू होते हैं और एक फ़ील्ड लेते हैं — data, एक base64-एन्कोडेड,
पहले से हस्ताक्षरित वायर payload जिसे कॉलर के अपने वॉलेट ने स्थानीय रूप से उत्पन्न किया।
यह Solana के sendTransaction को प्रतिबिंबित करता है: नोड कभी कॉलर की ओर से
कुछ भी संरचित या हस्ताक्षरित नहीं करता, वह केवल payload को डिकोड करता है और उसे उसी
हस्ताक्षर-सत्यापन पथ से लागू करता है जिससे एक gossip-प्राप्त इवेंट गुज़रता है।
{ "method": "sendReservationRequest", "params": { "data": "<base64 wire bytes>" } }
हर SDK का टाइप्ड Client वह payload आपके लिए बनाता और हस्ताक्षरित करता है —
यह वायर फ़ॉर्मैट को हाथ से बनाने के बजाय अनुशंसित एकीकरण बिंदु है।
मेथड श्रेणियाँ
| डोमेन | उदाहरण मेथड |
|---|---|
| विज्ञापन | getAdvertisement, getAdvertisements, sendAdvertisementCreate, sendAdvertisementPriceUpdate, sendAdvertisementDisable |
| आरक्षण | getReservation, getReservations, getMyReservations, sendReservationRequest |
| निपटान | getSettlement, getSettlements, getMySettlements, sendSettlementInitiate, sendPaymentSubmitted, sendSettlementApproved |
| व्यापार (केवल-पठन जॉइन) | getTrade, getTrades |
| विवाद | getDispute, getDisputes, getMyDisputes, sendDisputeOpen, sendArbitratorJoin, sendVoteCommit, sendVoteReveal |
| वॉलेट प्रूफ़ | getWalletChallenge, getCounterpartiesChallenge, getCounterparties, getProviderEarningsChallenge |
| आयतन | getSettledVolume |
| अटैचमेंट और सामग्री | getSettlementAttachments, getHeldContent, sendAttachmentPublish |
| पहचान | getIdentityClaim, getIdentityClaimsByWallet, sendClaimPublish |
| प्रतिष्ठा (केवल-पठन) | getReputation |
| शासन | getProposal, getProposals, sendProposalCreate, sendVoteCast |
| सेवा प्रदाता | getProvider, getProviders, sendProviderRegister, sendProviderHealthUpdate, getProviderEarnings, sendProviderWithdraw |
| सूचनाएँ | getSubscription, getNotificationDispatch, sendSubscriptionUpdate, sendDeliveryReport |
| ऑरेकल | getOracleRecord, getExchangeRate, getMedianExchangeRate, sendOraclePublish |
| जोखिम इंटेलिजेंस | getWalletScreening, sendRiskPublish |
| पुरस्कार | getRewardObservations |
| स्नैपशॉट | getLatestSnapshot, getSnapshots, getCheckpointSlot, sendSnapshotAnnounce |
| सत्र | getSession, sendSessionEstablish, sendSessionRenew, sendSessionRevoke, sendSessionMigrate |
| चेन ब्रिज (Solana, OFS-4300) | getChainStatus, getLatestBlockhash, sendTransaction |
| नोड | getVersion, getHealth, getPeers |
पठन जो पक्षों को नामित नहीं करते
getSettlement(s), getReservation(s) और getDispute(s) ऐसे रिकॉर्ड लौटाते हैं
जिनसे पक्ष की पहचान हटा दी गई है। यह एक चूक के बजाय एक जानबूझकर, सुरक्षा-प्रेरित
बदलाव है, और इसका अपना एक पृष्ठ है:
एक सार्वजनिक पठन क्या लौटाता है। एक पक्ष
वॉलेट-प्रूफ पठन के माध्यम से अपने रिकॉर्ड पूर्ण रूप में पढ़ता है।
विवाद चेन पर तय होते हैं, आपको उत्तर देने वाले नोड द्वारा नहीं
एक getDispute प्रतिक्रिया उन रिवील को ले जाती है जो एक नोड ने एकत्र किए हैं, और वह उनसे
व्युत्पन्न कोई परिणाम नहीं ले जाती। एक समाधान केवल तभी प्रकट होता है जब यह नोड
निष्पादन-कारी लेनदेन को पुष्ट होते देख चुका है और पढ़ चुका है कि उसने क्या तय किया —
देखें एक विवाद कैसे सुलझता है। एक क्लाइंट जो स्वयं
रिवील गिनता है, उसने ठीक वही विचलन फिर से लाया है जिसे नोड ने पैदा करना बंद कर दिया।
दो विनिमय-दर मेथड, और किसके लिए पहुँचें
getMedianExchangeRate एक नंगी संख्या या null लौटाता है, जो सही आकार है जब आप
केवल एक कीमत या कुछ भी नहीं चाहते।
getExchangeRate वही { base, quote } लेता है और इसके बजाय एक टैग की गई स्थिति से
उत्तर देता है, क्योंकि null दो भिन्न तथ्यों को ढहा देता है:
{ "status": "current", "rate": 129.5, "expiresAt": 1753800000000 }
{ "status": "stale" }
{ "status": "noData" }
अंतर अकादमिक नहीं है। Stale का अर्थ है कि एक प्रदाता यह जोड़ी प्रकाशित करता तो है और हर रिकॉर्ड समाप्त हो चुका है (OFS-7000 §12: समाप्त डेटा वर्तमान डेटा नहीं है, चाहे वह कितनी ही हाल में समाप्त हुआ हो) — फ़ीड के लौट आने की संभावना है, इसलिए प्रतीक्षा समझदारी है। NoData का अर्थ है कि इस गलियारे को कोई भी कीमत नहीं देता और प्रतीक्षा व्यर्थ है। कोई भी संख्या नहीं है, और एक कॉलर को किसी को भी संख्या के रूप में नहीं दिखाना चाहिए।
जब तक न करने का कोई कारण न हो, getExchangeRate के लिए पहुँचें। getMedianExchangeRate
बना रहता है क्योंकि क्लाइंट उस पर निर्भर हैं।
Service id
एक नोड node-<इसकी base58 सार्वजनिक कुंजी> के तहत पंजीकृत होता है, और एक स्नैपशॉट
प्रदाता snapshot-<वही कुंजी> के तहत — उपसर्ग वही है जो एक नोड को कई
रजिस्ट्री रिकॉर्ड बिना टकराए धारण करने देता है।
id यादृच्छिक होने के बजाय व्युत्पन्न है ताकि एक पुनः-आरंभ होता नोड अपना मौजूदा रिकॉर्ड अपडेट करे, न कि पीछे एक मृत प्रविष्टि छोड़े। इसे पूरी कुंजी से व्युत्पन्न करना मायने रखता है: एक पुरानी योजना peer id के पहले आठ बाइट को hex के रूप में इस्तेमाल करती थी, जो सोलह अंकों की पहचान जैसा दिखता है पर दो है, क्योंकि हर Ed25519 peer id उसी छह-बाइट प्रस्तावना से खुलता है। दो नोड कुछ ही सौ पंजीकरणों के भीतर टकरा गए, और दूसरा पंजीकृत होने वाला पहले को विस्थापित कर गया।
एक नोड नेटवर्क के बारे में क्या जानता है
getPeers उन peers की रिपोर्ट देता है जिन्हें इस नोड ने खोजा है, वे पते जो यह अपने बारे में
घोषित करता है, और उसका अपना self_peer_id उस 12D3Koo… रूप में जो एक
--entrypoint में जाता है। इसके ऑपरेटर दृष्टिकोण के लिए
peer खोज देखें।
त्रुटियाँ
मानक JSON-RPC 2.0 त्रुटि कोड (-32700 पार्स त्रुटि, -32601 मेथड नहीं
मिला, -32602 अमान्य पैरामीटर, -32603 आंतरिक त्रुटि) परिवहन-स्तर की
विफलताओं को कवर करते हैं। हर डोमेन विफलता — अपर्याप्त तरलता, एक डुप्लिकेट
इवेंट, एक अनधिकृत हस्ताक्षरकर्ता — एक ही -32000 एप्लिकेशन त्रुटि के रूप में
वापस आती है, प्रोटोकॉल के अपने संख्यात्मक कोड और प्रतीकात्मक नाम (से
OFS-8000) के साथ data में:
{ "error": { "code": -32000, "message": "INSUFFICIENT_AVAILABLE_LIQUIDITY", "data": { "ofsErrorCode": 4004, "ofsErrorName": "INSUFFICIENT_AVAILABLE_LIQUIDITY" } } }
सब्सक्रिप्शन
GET /ws
हर सफल परिवर्तन को जैसे ही होता है स्ट्रीम करता है — {"method": "sendX", "result": ...} — ताकि एक क्लाइंट बिना पोलिंग के बाज़ार गतिविधि पर प्रतिक्रिया कर सके। जिन मेथड की आपको परवाह है उनके लिए क्लाइंट-साइड फ़िल्टर करें।
स्नैपशॉट एक height के बजाय एक slot से टैग होते हैं
getCheckpointSlot वह Solana slot लौटाता है जिसके अनुसार अंतिम आयातित स्नैपशॉट की
स्थिति वर्तमान थी, या ऐसे नोड पर null जिसने कोई आयात नहीं किया।
यह getCheckpointHeight था, और यह नाम बदलना सजावटी नहीं है। पुराना मान
उत्पादक नोड की gossip इवेंटों की अपनी गिनती था, जो प्रति-उत्पादक है:
समान स्थिति धारण करने वाले दो नोड भिन्न संख्याएँ रिपोर्ट करते हैं, और एक
पिछले सप्ताह जुड़ा नोड, जेनेसिस से चल रहे नोड से नीचे की रिपोर्ट देता है।
दो उत्पादकों की संख्याओं की तुलना कुछ भी तुलना नहीं करती थी।
एक slot वह एक घड़ी है जो हर भागीदार पहले से साझा करता है। यह एक दावे को जाँच-योग्य भी बनाता है — एक नोड एक घोषित slot की तुलना चेन के अपने ही दृष्टिकोण से कर सकता है और एक अकल्पनीय भविष्य से एक को अस्वीकार कर सकता है, जो कि केवल घोषक द्वारा देखी जा सकने वाली संख्या के विरुद्ध असंभव है।
एक slot जो दावा करता है वह दिखने से संकरा है। यह कहता है कि स्थिति कब कैद की गई, न कि उसमें क्या है: एक ही slot पर स्नैपशॉट लेने वाले दो नोड थोड़ी भिन्न gossip स्थिति धारण कर सकते हैं, क्योंकि प्रसार तत्काल नहीं है। इसे एक निकटता एंकर मानें, इस प्रमाण के रूप में नहीं कि एक स्नैपशॉट दूसरे को समाहित करता है — वही जो Solana के अपने स्नैपशॉट इससे अर्थ रखते हैं।
एक नोड जिसने कभी एक slot नहीं देखा, कोई स्नैपशॉट नहीं बनाता और यही कहता है। यह एक RPC कनेक्शन चलाने की आवश्यकता नहीं है: एक gossip-only नोड चेन ब्रिज पर slots सीखता है।
निपटाया गया आयतन, और यह प्रति-संपत्ति क्यों है
getSettledVolume प्रति संपत्ति एक पंक्ति से उत्तर देता है, कभी एक कुल नहीं:
{
"assets": [
{ "asset_mint": "2bHPi…RRU", "asset_symbol": "USDC", "decimals": 6,
"base_units": 4500000, "settlements": 12 },
{ "asset_mint": "So111…112", "asset_symbol": "wSOL", "decimals": 9,
"base_units": 2000000000, "settlements": 3 }
],
"unattributed_settlements": 1,
"settlements_known": 16,
"scope": "settlements this node has replicated and observed confirmed"
}
इसके साथ चार चीज़ें एक क्लाइंट को नहीं करनी चाहिए:
संपत्तियों के बीच योग मत करो। वे भिन्न पैमानों पर भिन्न टोकन हैं; एक संयुक्त आँकड़ा SOL को USDC में जोड़ता है और कुछ अर्थ नहीं रखता।
decimals का अनुमान मत लगाओ। जब इस नोड के पास उस mint का कोई नाम नहीं होता,
तब यह एक null asset_symbol के साथ null होता है। पता और कच्ची base units
दिखाओ। 6 मान लेना ठीक वह है जिससे wSOL — जिसके नौ हैं — हज़ार गुना बहुत
बड़ा निकलता है।
unattributed_settlements मत छिपाओ। वे असली पुष्ट निपटान हैं जिनका विज्ञापन
तब से हटा दिया गया है, इसलिए उनकी संपत्ति अपुनर्प्राप्य है। उन्हें छोड़ना कुल को
पूर्ण दिखाता है जबकि वे उतने ही कम हैं।
scope मत गिराओ। यह कहता है कि ये वे निपटान हैं जो इस नोड ने
प्रतिकृत और पुष्ट किए — पूरे नेटवर्क का इतिहास नहीं। अपने दायरे के बिना
प्रस्तुत एक आयतन आँकड़ा एक वैश्विक कुल के रूप में पढ़ा जाता है। गिनी गई पंक्तियों
के पास settlements_known शेष को एक विसंगति के बजाय गतिमान व्यापार के रूप में
पढ़ने देता है।
इंटरैक्टिव संदर्भ
एक OpenRPC 1.2.6 दस्तावेज़ (एक OpenAPI/Swagger spec का
JSON-RPC समतुल्य) — /api/openrpc.json —
साथ ही हर मेथड ब्राउज़ करने के लिए एक स्वयं-निहित इंटरैक्टिव पृष्ठ। मेथड सूची
सीधे openfiat-rpc की अपनी जीवंत डिस्पैच तालिका से उत्पन्न होती है
(cargo run -p openfiat-api --example dump_openrpc), इसलिए यह एक ऐसे मेथड पर नहीं
बहक सकती जिसे एक असली नोड नहीं चलाता; इसे यहाँ एक स्थिर स्नैपशॉट के रूप में
प्रकाशित किया गया है क्योंकि इस डॉक्स साइट के पास इसे जीवंत परोसने के लिए अपना कोई नोड
नहीं है। संदर्भ पृष्ठ के «Try it» पैनल को अपने स्वयं चला रहे एक नोड पर इंगित करें (डिफ़ॉल्ट
http://localhost:7080) ताकि किसी मेथड को सचमुच कॉल किया जा सके।
उस दस्तावेज़ में प्रति-मेथड स्कीमा एक जानबूझकर सरलीकृत, परिपाटी-आधारित
सन्निकटन हैं — हर getX(id) {id} लेता है, हर sendX {data} लेता है — न कि हर
मेथड के ठोस Rust प्रकारों से व्युत्पन्न JSON Schema। जहाँ एक मेथड उन परिपाटियों से
हटता है, वहाँ यह साइट प्राधिकारी आकार है: वॉलेट-प्रूफ पठन,
getExchangeRate और getPeers सभी ऐसे पैरामीटर लेते हैं जिन्हें परिपाटी वर्णित
नहीं करती।
एक चल रहा नोड भी अपने ही /rpc के साथ समान संदर्भ को जीवंत और सम-मूल परोसता है:
GET /openrpc.json और GET /docs। GET /metrics ऑपरेटरों के लिए Prometheus-प्रारूप
अनुरोध काउंटर उजागर करता है।