
Web3.Swift هي مكتبة سريعة لتوقيع المعاملات والتفاعل مع العقود الذكية في شبكة Ethereum.
يتيح لك الاتصال بعقدة Geth أو Erigon Ethereum (مثل Chainnodes) لإرسال المعاملات وقراءة القيم من العقود الذكية دون الحاجة إلى كتابة تطبيقاتك الخاصة للبروتوكولات.
Web3.Swift يدعم iOS و MacOS و TVOS و WatchOS و Linux مع Swift Package Manager.
تحقق من الاستخدام أدناه أو ابحث عن اختبارات المستودعات.
هناك بالفعل بعض مكتبة Web3 مكتوبة في Swift. نحن نعرف نقاط القوة والضعف الخاصة بهم ولحالة استخدامنا لم ينجحوا.
Web3.swift تم تصميمه مع النموذج ، قابلية النقل ، السرعة والكفاءة في الاعتبار.
حسنًا ، شكرًا لك على الكلمات الطنانة. ولكن ماذا يعني هذا في الواقع؟
Web3.swift تم تصميمه ليكون وحدات. إذا قمت بتثبيت/استخدام منتج Web3 SPM الأساسي ، يمكنك الوصول إلى أكثر الوظائف الأساسية مثل توقيع المعاملات والتفاعل مع خادم HTTP RPC.
إذا كنت ترغب في إضافة دعم لـ IPC RPC أو أي شيء آخر ، فيمكنك إنشاء مكتبة بسيطة تعتمد على Web3 وتنفيذ هذه الوظيفة الدقيقة. المزيد عن ذلك لاحقًا.
إذا كنت ترغب في استخدام ملحقات PromiseKit لمكالمات Web3 ، فيمكنك إما استخدام منتج PromiseKit SPM المقدم أو إنشاء خاص بك.
إذا كنت ترغب في تحليل JSON ABIS بشكل مريح لعقود Ethereum الذكية ، فيمكنك استخدام منتج ABI Parsing SPM المقدم.
أخيرًا ، إذا كنت ترغب في إضافة وظائف إلى Web3.swift التي لم يتم توفيرها بعد ، فلن تضطر إلى الانتظار حتى يتم دمجها وإصدارها في عثرة الإصدار. يمكنك تمديد/تحديث وظائف Simple داخل التطبيق الخاص بك لأن واجهات برمجة التطبيقات لدينا مصنوعة لتكون مفتوحة للغاية للتغييرات.
على سبيل المثال ، إذا كنت ترغب في إضافة طريقة Web3 التي لم يتم توفيرها حتى الآن بواسطة Web3.swift (سندعم فقط الطرق المدعومة من Infura) ، فيجب عليك فقط إضافة 3 أسطر من التعليمات البرمجية (اعتمادًا على معلمات الإدخال والإخراج للطريقة). إن إضافة دعم IPC RPC سيكون فقط تنفيذ بروتوكول والرد على طلبات الرد.
كما ترون ، كل شيء ممكن مع Web3.swift .
أحد الأسباب الرئيسية التي بدأنا في العمل في هذا المشروع هو أننا أردنا استخدامه مع Swift Package Manager على منصات مختلفة.
ولهذا السبب ، يتوفر Web3.swift من خلال Swift Package Manager على iOS و MacOS و TVOS و Watchos و Linux.
ملاحظة: بالنسبة إلى SPM ، نقوم فقط باختبار iOS و MACOS وتوزيعات Linux المدعومة رسميًا (حاليًا Ubuntu 16.04 و 20.04) ولكن يجب أن تكون متوافقة مع جميع الأنظمة الإندينية الصغيرة التي يمكنها تجميع المترجم السريع والمؤسسة و GLIBC.
نحاول جعل هذه المكتبة في أسرع وقت ممكن أثناء محاولة توفير واجهة برمجة تطبيقات تزيد من سير عمل التنمية الخاص بك بحيث يمكنك التركيز على بناء DAPPs الرائعة بدلاً من القلق بشأن تفاصيل التنفيذ.
جميع واجهات برمجة التطبيقات الخاصة بنا آمنة ومصممة لاستخدامها في التطبيقات المتزامنة للغاية.
Web3 متوافق مع Swift Package Manager V5 (Swift 5 وما فوق). ما عليك سوى إضافته إلى التبعيات في Package.swift الخاصة بك.
dependencies: [
. package ( url : " https://github.com/Boilertalk/Web3.swift.git " , from : " 0.6.0 " )
]ثم أضفه إلى تبعياتك المستهدفة:
targets: [
. target (
name : " MyProject " ,
dependencies : [
. product ( name : " Web3 " , package : " Web3.swift " ) ,
. product ( name : " Web3PromiseKit " , package : " Web3.swift " ) ,
. product ( name : " Web3ContractABI " , package : " Web3.swift " ) ,
]
) ,
. testTarget (
name : " MyProjectTests " ,
dependencies : [ " MyProject " ] )
]ملاحظة: يعد
Web3PromiseKitوWeb3ContractABIاختياريًا وعليك فقط وضعها في تبعياتك المستهدفة (واستيرادها لاحقًا) إذا كنت ترغب في استخدامها.
بعد التثبيت ، يمكنك استيراد Web3 في ملفات .swift الخاصة بك.
import Web3
// Optional
import Web3PromiseKit
import Web3ContractABIبسبب قرار داخلي ، توقفنا عن دعم أي مديري حزم بخلاف SPM بدءًا من الإصدار 0.5.0.
لتوضيح هذا القرار قليلاً: مع Xcode 11 و Swift 5.1 ، وصلنا إلى نقطة مع Swift Package Manager حيث بدأت ببطء في جعل مديري الحزم الآخرين غير ذي صلة. يمكنك بالفعل تحميل جميع تبعياتك في مشروع Xcode مع Swift Package Manager.
مع المزيد من التحديثات أصبح أكثر انتشارًا. فقدت Cocoapods و Carthage Mainters اهتمامهم بمشروعهم وتوقفوا عن الحفاظ عليه. هناك العديد من المشكلات التي لم يتم حلها ، والكثير من المشكلات خاصة لمطوري المكتبات الذين يعانون من الكوكورات.
الكثير من المتاعب لعدم وجود مكسب حقيقي. يمكن للمستخدمين بالفعل وضع تبعيات تدعم SPM في مشروع XCode الخاص بهم. فلماذا تهتم؟
الجواب بسيط. لا يزال البعض يستخدم Xcode <11 وبعض مطوري المكتبات يعتمدون على Web3 في القرون/قرودهم.
كان القرار صعبًا واستغرق بعض الوقت. ولكن بعد رؤية أن الإصدار الأخير كان مستقرًا للغاية ويستخدم في العديد من تطبيقات الإنتاج بالفعل ، قررنا أن نبدأ بهذه الخطوة الآن.
XCODE 10 عمره بالفعل أكثر من عامين. معظم المشاريع التي تمت ترقيتها بالفعل ، تلك التي لم تكن لديها مشكلة أكبر بكثير من الويب.
يتم تشجيع أصحاب المكتبات اعتمادًا على الويب.
SPM هو المستقبل. بالنسبة لجميع مستخدمي Cocoapods و Carthage الذين يستخدمونها لأن العديد من المكتبات لم تتحول إلى SPM حتى الآن: لا يزال بإمكانك إضافة Web3.Swift كمنتج SPM في .xcworkspace أو .xcodeproj والحفاظ على جميع تبعياتك الأخرى داخل Cocoapods/carthage. ولكن لا يزال. نشجعك على التبديل مع أكبر عدد ممكن من التبعيات إلى SPM. أفضل عاجلاً وليس آجلاً. انظر القسم التالي حول كيفية القيام بذلك.
باستخدام Xcode 11 أو أحدث (لنظام التشغيل iOS أو MacOs أو منصات Apple الأخرى) ، يمكنك إضافة حزم SPM سهلة للغاية.
في Xcode ، حدد مشروعك ، من القائمة المنسدلة ، حدد المشروع ، وليس هدفًا واحدًا ، في علامات التبويب ، حدد Swift Packages .
ثم يمكنك النقر فوق أيقونة + ووضعها في عنوان URL على هذا المستودع (https://github.com/boilertalk/web3.swift).
يمكنك الآن تحديد جميع المنتجات والنقر فوق التالي حتى تمت إضافة التبعية.
هذا كل شيء. إذا دفعت التغييرات الخاصة بك ، فإن CI لن تواجه أي مشاكل. لا توجد متاعب مع مستودعات المواصفات التي عفا عليها الزمن ، لا توجد مشاكل مع بعض أخطاء الرابط الغريبة التي تحدث في بعض الأحيان/مع بعض التبعيات.
إذا كنت بحاجة إلى مزيد من التوجيه ، انضم إلى مجموعة Telegram وسنساعدك. https://t.me/web3_swift
باستخدام Web3.swift يمكنك استخدام عقدة Ethereum على خادم للتواصل مع Ethereum.
يمكنك إرسال معاملات موقعة ، وقراءة بيانات العقد ، ووظائف عقد الاتصال وأكثر من ذلك بكثير.
الفئة الأساسية لجميع الأساليب المتاحة هي Web3 . يمكنك ، على سبيل المثال ، إنشاء مثيل لها مع مزود HTTP:
let web3 = Web3 ( rpcURL : " https://mainnet.infura.io/<your_infura_id> " ) جميع طرق web3_ متوفرة مباشرة من Web3 Struct. تتوفر أساليب net_ ضمن The net Struct في web3 Struct. تتوفر طرق eth_ ضمن بنية eth في بنية web3 .
يرجى الاطلاع على الأمثلة أدناه
ملاحظة: بالنسبة للأمثلة ، تحتاج إلى استيراد Web3 و PromiseKit أولاً
إرجاع إصدار العميل الحالي.
حدود
لا أحد
عودة
String - إصدار العميل الحالي
firstly {
web3 . clientVersion ( )
} . done { version in
print ( version )
} . catch { error in
print ( " Error " )
} إرجاع معرف الشبكة الحالي.
حدود
لا أحد
عودة
String - معرف الشبكة الحالي
firstly {
web3 . net . version ( )
} . done { version in
print ( version )
} . catch { error in
print ( " Error " )
} إرجاع عدد أقرانهم المتصلون حاليًا بالعميل.
حدود
لا أحد
عودة
EthereumQuantity - Bigint لعدد أقرانهم المتصلين.
firstly {
web3 . net . peerCount ( )
} . done { ethereumQuantity in
print ( ethereumQuantity . quantity )
} . catch { error in
print ( " Error " )
} ينشئ معاملة مكالمة رسائل جديدة أو إنشاء عقد للمعاملات الموقعة.
حدود
EthereumTransaction : الصفقة الموقعةعودة
EthereumData ، 32 بايت - تجزئة المعاملة ، أو تجزئة الصفر إذا لم تكن المعاملة متوفرة بعد
لإرسال بعض ETH ، تحتاج أولاً إلى الحصول على عدد المعاملات الحالية للمرسل (NONCE) ، وإنشاء المعاملة ، وتوقيعها ثم إرسالها.
let privateKey = try ! EthereumPrivateKey ( hexPrivateKey : " 0xa26da69ed1df3ba4bb2a231d506b711eace012f1bd2571dfbfff9650b03375af " )
firstly {
web3 . eth . getTransactionCount ( address : privateKey . address , block : . latest )
} . then { nonce in
let tx = try EthereumTransaction (
nonce : nonce ,
gasPrice : EthereumQuantity ( quantity : 21 . gwei ) ,
gas : 21000 ,
to : EthereumAddress ( hex : " 0xC0866A1a0ed41e1aa75c932cA3c55fad847fd90D " , eip55 : true ) ,
value : EthereumQuantity ( quantity : 1 . eth )
)
return try tx . sign ( with : privateKey , chainId : 1 ) . promise
} . then { tx in
web3 . eth . sendRawTransaction ( transaction : tx )
} . done { hash in
print ( hash )
} . catch { error in
print ( error )
} firstly {
web3 . eth . getBlockTransactionCountByNumber ( block : . block ( 5397389 ) )
} . done { count in
print ( count ) // 88
} . catch { error in
print ( error )
} لمزيد من الأمثلة إما قراءة من خلال حالات الاختبار الخاصة بنا ، فإن Web3 Struct أو وثائق Ethereum JSON RPC الرسمية.
نحن نقدم وحدة اختيارية للتفاعل مع العقود الذكية. لاستخدامه ، عليك إضافة Web3ContractABI إلى تبعياتك المستهدفة في PODFile (لـ SPM). تأكد من مراجعة تعليمات التثبيت أولاً.
نحن نقدم خيارين مختلفين لإنشاء واجهات ABI العقد في Swift. إما أن تحدد وظائفك وأحداثك يدويًا (أو تستخدم إحدى واجهاتنا المقدمة مثل ERC20 أو ERC721). أو أنك تحليلهم من تمثيل JSON ABI كما هو الحال في Web3.JS.
العقود الثابتة هي فصول تنفيذ StaticContract . أنها توفر مجموعة من الوظائف والأحداث التي يرغبون في استخدامها من العقد الذكي الأصلي. تحقق من عقودنا الثابتة المقدمة كنقطة انطلاق (ERC20 أو ERC721).
تسمى واجهة ERC20 الثابتة لدينا GenericERC20Contract ، ويسمى عقد ERC721 GenericERC721Contract . يمكن أن يكون كلاهما فئة فرعية لإضافة المزيد من الوظائف للعقود المخصصة.
باستخدام أنواع StaticContract يمكنك إنشاء عقدك واستخدامه كما هو الحال في المثال التالي (نحن نستخدم PromiseKit مرة أخرى في أمثلةنا).
let web3 = Web3 ( rpcURL : " https://mainnet.infura.io/<your_infura_id> " )
let contractAddress = try EthereumAddress ( hex : " 0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0 " , eip55 : true )
let contract = web3 . eth . Contract ( type : GenericERC20Contract . self , address : contractAddress )
// Get balance of some address
firstly {
try contract . balanceOf ( address : EthereumAddress ( hex : " 0x3edB3b95DDe29580FFC04b46A68a31dD46106a4a " , eip55 : true ) ) . call ( )
} . done { outputs in
print ( outputs [ " _balance " ] as? BigUInt )
} . catch { error in
print ( error )
}
// Send some tokens to another address (locally signing the transaction)
let myPrivateKey = try EthereumPrivateKey ( hexPrivateKey : " ... " )
firstly {
web3 . eth . getTransactionCount ( address : myPrivateKey . address , block : . latest )
} . then { nonce in
try contract . transfer ( to : EthereumAddress ( hex : " 0x3edB3b95DDe29580FFC04b46A68a31dD46106a4a " , eip55 : true ) , value : 100000 ) . createTransaction (
nonce : nonce ,
gasPrice : EthereumQuantity ( quantity : 21 . gwei ) ,
maxFeePerGas : nil ,
maxPriorityFeePerGas : nil ,
gasLimit : 100000 ,
from : myPrivateKey . address ,
value : 0 ,
accessList : [ : ] ,
transactionType : . legacy
) ! . sign ( with : myPrivateKey ) . promise
} . then { tx in
web3 . eth . sendRawTransaction ( transaction : tx )
} . done { txHash in
print ( txHash )
} . catch { error in
print ( error )
}
// Send some tokens to another address (signing will be done by the node)
let myAddress = try EthereumAddress ( hex : " 0x1f04ef7263804fafb839f0d04e2b5a6a1a57dc60 " , eip55 : true )
firstly {
web3 . eth . getTransactionCount ( address : myAddress , block : . latest )
} . then { nonce in
try contract . transfer ( to : EthereumAddress ( hex : " 0x3edB3b95DDe29580FFC04b46A68a31dD46106a4a " , eip55 : true ) , value : 100000 ) . send (
nonce : nonce ,
gasPrice : EthereumQuantity ( quantity : 21 . gwei ) ,
maxFeePerGas : nil ,
maxPriorityFeePerGas : nil ,
gasLimit : 150000 ,
from : myAddress ,
value : 0 ,
accessList : [ : ] ,
transactionType : . legacy
)
} . done { txHash in
print ( txHash )
} . catch { error in
print ( error )
}من خلال إنشاء واجهاتك الخاصة ، يمكنك التفاعل مع أي عقد ذكي!
إذا كان لديك فقط الوصول إلى JSON ABI من عقد ذكي أو لا ترغب في إنشاء قالب ثابت ، فيمكنك استخدام واجهة برمجة تطبيقات العقد الديناميكي لتحليل سلسلة JSON في عقد قابل للاستخدام أثناء وقت التشغيل . انظر المثال أدناه.
let web3 = Web3 ( rpcURL : " https://mainnet.infura.io/<your_infura_id> " )
let contractAddress = try EthereumAddress ( hex : " 0x86fa049857e0209aa7d9e616f7eb3b3b78ecfdb0 " , eip55 : true )
let contractJsonABI = " <your contract ABI as a JSON string> " . data ( using : . utf8 ) !
// You can optionally pass an abiKey param if the actual abi is nested and not the top level element of the json
let contract = try web3 . eth . Contract ( json : contractJsonABI , abiKey : nil , address : contractAddress )
print ( contract . methods . count )
// Get balance of some address
firstly {
try contract [ " balanceOf " ] ! ( EthereumAddress ( hex : " 0x3edB3b95DDe29580FFC04b46A68a31dD46106a4a " , eip55 : true ) ) . call ( )
} . done { outputs in
print ( outputs [ " _balance " ] as? BigUInt )
} . catch { error in
print ( error )
}
// Send some tokens to another address (locally signing the transaction)
let myPrivateKey = try EthereumPrivateKey ( hexPrivateKey : " ... " )
guard let transaction = contract [ " transfer " ] ? ( EthereumAddress . testAddress , BigUInt ( 100000 ) ) . createTransaction (
nonce : 0 ,
gasPrice : EthereumQuantity ( quantity : 21 . gwei ) ,
maxFeePerGas : nil ,
maxPriorityFeePerGas : nil ,
gasLimit : 150000 ,
from : myPrivateKey . address ,
value : 0 ,
accessList : [ : ] ,
transactionType : . legacy
) ) else {
return
}
let signedTx = try transaction . sign ( with : myPrivateKey )
firstly {
web3 . eth . sendRawTransaction ( transaction : signedTx )
} . done { txHash in
print ( txHash )
} . catch { error in
print ( error )
}باستخدام واجهة برمجة التطبيقات هذه ، يمكنك التفاعل مع أي عقد ذكي في شبكة Ethereum!
لمزيد من الأمثلة ، بما في ذلك إنشاء العقد (استدعاء مُنشئ) تحقق من اختباراتنا.
إذا كنت تحصل على هذا الخطأ عند تحليل ABI الخاص بك من JSON ، فقد يكون ذلك لأن العقد الخاص بك لديه وظيفة احتياطي. لحلها ، قم بإزالة جزء ABI الخاص بك الذي يحتوي على معلومات حول وظيفة الاحتياطية. قد يبدو الجزء الذي يجب إزالته هكذا:
{
"payable": false,
"stateMutability": "nonpayable",
"type": "fallback"
},
حتى نصل إلى الإصدار 1.0.0 تخضع واجهة برمجة التطبيقات الخاصة بنا لتغيير التغييرات بين القفزات البسيطة. هذا هو التأكد من أنه يمكننا التركيز على توفير أفضل تطبيق أثناء التنمية الثقيلة بدلاً من محاولة الحفاظ على شيء تم إهماله.
ومع ذلك ، سنحاول تقليل التغييرات في كسر. بالتأكيد لن يكون هناك الكثير.
الرجال الرائعين في Boilertalk ⚗
... وحتى أعضاء أكثر رهيبة من المجتمع؟
تحقق من قائمة المساهمين للحصول على قائمة كاملة.
Web3 متاح بموجب ترخيص MIT. انظر ملف الترخيص لمزيد من المعلومات.