Αυτός ο οδηγός περιγράφει πώς να προσθέσετε το εγγενές token SOL της Solana στο ανταλλακτήριο κρυπτονομισμάτων σας.
Ρύθμιση Κόμβου
Συνιστούμε ανεπιφύλακτα να ρυθμίσετε τουλάχιστον δύο κόμβους σε υπολογιστές υψηλών προδιαγραφών ή cloud instances, να αναβαθμίζετε σε νεότερες εκδόσεις άμεσα και να παρακολουθείτε τις λειτουργίες της υπηρεσίας με ένα ενσωματωμένο εργαλείο παρακολούθησης.
Αυτή η ρύθμιση σάς επιτρέπει:
- να έχετε μια αυτοδιαχειριζόμενη πύλη πρόσβασης στο cluster mainnet της Solana για λήψη δεδομένων και υποβολή συναλλαγών ανάληψης
- να έχετε πλήρη έλεγχο του πόσα ιστορικά δεδομένα block διατηρούνται
- να διατηρείτε τη διαθεσιμότητα της υπηρεσίας σας ακόμα και αν αποτύχει ένας κόμβος
Οι κόμβοι Solana απαιτούν σχετικά υψηλή υπολογιστική ισχύ για τη διαχείριση των γρήγορων block και του υψηλού TPS. Για συγκεκριμένες απαιτήσεις, δείτε προτάσεις υλικού.
Για να εκτελέσετε έναν κόμβο api:
- Εγκαταστήστε τη σουίτα εργαλείων γραμμής εντολών της Solana
- Εκκινήστε τον validator με τουλάχιστον τις παρακάτω παραμέτρους:
solana-validator \--ledger <LEDGER_PATH> \--identity <VALIDATOR_IDENTITY_KEYPAIR> \--entrypoint <CLUSTER_ENTRYPOINT> \--expected-genesis-hash <EXPECTED_GENESIS_HASH> \--rpc-port 8899 \--no-voting \--enable-rpc-transaction-history \--limit-ledger-size \--known-validator <VALIDATOR_ADDRESS> \--only-known-rpc
Προσαρμόστε το --ledger στη θέση αποθήκευσης ledger που επιθυμείτε, και το --rpc-port στη θύρα που θέλετε να εκθέσετε.
Οι παράμετροι --entrypoint και --expected-genesis-hash είναι ειδικές για το cluster στο οποίο εντάσσεστε.
Τρέχουσες παράμετροι για το Mainnet
Η παράμετρος --limit-ledger-size σάς επιτρέπει να ορίσετε πόσα shreds του ledger διατηρεί ο κόμβος σας στο δίσκο. Εάν δεν συμπεριλάβετε αυτή την παράμετρο, ο validator θα διατηρεί ολόκληρο το ledger μέχρι να εξαντληθεί ο χώρος στο δίσκο. Η προεπιλεγμένη τιμή επιχειρεί να διατηρεί τη χρήση δίσκου του ledger κάτω από 500GB. Περισσότερη ή λιγότερη χρήση δίσκου μπορεί να ζητηθεί προσθέτοντας ένα όρισμα στο --limit-ledger-size εάν το επιθυμείτε. Ελέγξτε το solana-validator --help για την προεπιλεγμένη τιμή ορίου που χρησιμοποιεί το --limit-ledger-size. Περισσότερες πληροφορίες σχετικά με την επιλογή προσαρμοσμένης τιμής ορίου είναι διαθέσιμες εδώ.
Ο καθορισμός μίας ή περισσότερων παραμέτρων --known-validator μπορεί να σας προστατεύσει από εκκίνηση από ένα κακόβουλο snapshot.
Περισσότερα για την αξία εκκίνησης με γνωστούς validators
Προαιρετικές παράμετροι που αξίζει να εξετάσετε:
--private-rpcαποτρέπει τη δημοσίευση της θύρας RPC σας για χρήση από άλλους κόμβους--rpc-bind-addressσάς επιτρέπει να ορίσετε διαφορετική διεύθυνση IP για τη σύνδεση της θύρας RPC
Αυτόματες Επανεκκινήσεις και Παρακολούθηση
Συνιστούμε να ρυθμίσετε κάθε κόμβο σας ώστε να επανεκκινεί αυτόματα μετά από έξοδο, για να διασφαλίσετε ότι χάνετε όσο το δυνατόν λιγότερα δεδομένα. Η εκτέλεση του λογισμικού solana ως υπηρεσία systemd είναι μια εξαιρετική επιλογή.
Για παρακολούθηση, παρέχουμε το
solana-watchtower,
το οποίο μπορεί να παρακολουθεί τον validator σας και να ανιχνεύει εάν η διεργασία solana-validator είναι ανθυγιεινή. Μπορεί να ρυθμιστεί άμεσα για να σας ειδοποιεί μέσω Slack, Telegram, Discord ή Twilio. Για λεπτομέρειες, εκτελέστε solana-watchtower --help.
solana-watchtower --validator-identity <YOUR VALIDATOR IDENTITY>
Μπορείτε να βρείτε περισσότερες πληροφορίες σχετικά με τις βέλτιστες πρακτικές για το Solana Watchtower εδώ στα έγγραφα.
Ανακοινώσεις Νέων Εκδόσεων Λογισμικού
Κυκλοφορούμε νέο λογισμικό συχνά (περίπου 1 έκδοση / εβδομάδα). Μερικές φορές οι νεότερες εκδόσεις περιλαμβάνουν μη συμβατές αλλαγές πρωτοκόλλου, οι οποίες απαιτούν έγκαιρη ενημέρωση λογισμικού για αποφυγή σφαλμάτων στην επεξεργασία block.
Οι επίσημες ανακοινώσεις κυκλοφορίας για όλα τα είδη εκδόσεων (κανονικές και ασφαλείας) κοινοποιούνται μέσω ενός καναλιού discord με την ονομασία
#mb-announcement (mb σημαίνει mainnet-beta).
Όπως και οι validators με stake, αναμένουμε από τους validators που λειτουργούν ανταλλακτήρια να ενημερώνονται το συντομότερο δυνατό, εντός μίας έως δύο εργάσιμων ημερών μετά από μια κανονική ανακοίνωση έκδοσης. Για εκδόσεις που αφορούν ασφάλεια, ενδέχεται να απαιτείται πιο άμεση δράση.
Συνέχεια Ledger
Από προεπιλογή, κάθε κόμβος σας θα εκκινεί από ένα snapshot που παρέχεται από έναν από τους γνωστούς validators σας. Αυτό το snapshot αντικατοπτρίζει την τρέχουσα κατάσταση της αλυσίδας, αλλά δεν περιέχει το πλήρες ιστορικό ledger. Εάν ένας από τους κόμβους σας τερματιστεί και εκκινήσει από νέο snapshot, ενδέχεται να υπάρχει κενό στο ledger σε εκείνον τον κόμβο. Για να αποτρέψετε αυτό το πρόβλημα, προσθέστε την παράμετρο --no-snapshot-fetch στην εντολή solana-validator για να λαμβάνετε ιστορικά δεδομένα ledger αντί για snapshot.
Μην περνάτε την παράμετρο --no-snapshot-fetch κατά την αρχική εκκίνηση, καθώς δεν είναι δυνατή η εκκίνηση του κόμβου εξ ολοκλήρου από το genesis block. Αντ' αυτού, εκκινήστε πρώτα από ένα snapshot και στη συνέχεια προσθέστε την παράμετρο --no-snapshot-fetch για επανεκκινήσεις.
Είναι σημαντικό να σημειωθεί ότι το ιστορικό ledger που είναι διαθέσιμο στους κόμβους σας από το υπόλοιπο δίκτυο είναι περιορισμένο ανά πάσα στιγμή. Μόλις τεθούν σε λειτουργία, εάν οι validators σας παρουσιάσουν σημαντικό χρόνο εκτός λειτουργίας, ενδέχεται να μην μπορούν να συγχρονιστούν με το δίκτυο και θα χρειαστεί να κατεβάσουν νέο snapshot από έναν γνωστό validator. Κάνοντας αυτό, οι validators σας θα έχουν πλέον ένα κενό στα ιστορικά δεδομένα ledger που δεν μπορεί να καλυφθεί.
Ελαχιστοποίηση Έκθεσης Θυρών Validator
Ο validator απαιτεί διάφορες θύρες UDP και TCP να είναι ανοικτές για εισερχόμενη κίνηση από όλους τους άλλους validators της Solana. Αν και αυτή είναι η πιο αποδοτική λειτουργία και συνιστάται ανεπιφύλακτα, είναι δυνατό να περιοριστεί ο validator ώστε να απαιτεί εισερχόμενη κίνηση μόνο από έναν άλλο validator της Solana.
Αρχικά προσθέστε το όρισμα --restricted-repair-only-mode. Αυτό θα κάνει τον validator να λειτουργεί σε περιορισμένη λειτουργία όπου δεν θα λαμβάνει pushes από τους υπόλοιπους validators, και αντ' αυτού θα πρέπει να ρωτά συνεχώς άλλους validators για block. Ο validator θα μεταδίδει μόνο πακέτα UDP σε άλλους validators χρησιμοποιώντας τις θύρες Gossip και ServeR ("serve repair"), και θα λαμβάνει μόνο πακέτα UDP στις θύρες Gossip και Repair του.
Η θύρα Gossip είναι αμφίδρομη και επιτρέπει στον validator σας να παραμένει σε επαφή με το υπόλοιπο cluster. Ο validator σας μεταδίδει στη ServeR για να υποβάλλει αιτήματα επισκευής και να αποκτά νέα block από το υπόλοιπο δίκτυο, καθώς το Turbine είναι πλέον απενεργοποιημένο. Ο validator σας θα λαμβάνει στη συνέχεια απαντήσεις επισκευής στη θύρα Repair από άλλους validators.
Για να περιορίσετε περαιτέρω τον validator ώστε να ζητά block μόνο από έναν ή περισσότερους validators, προσδιορίστε πρώτα το pubkey ταυτότητας για εκείνον τον validator και προσθέστε τα ορίσματα --gossip-pull-validator PUBKEY --repair-validator PUBKEY για κάθε PUBKEY. Αυτό θα προκαλέσει στον validator σας να αποτελεί επιβάρυνση πόρων για κάθε validator που προσθέτετε, οπότε κάντε το αυτό με φειδώ και μόνο αφού συνεννοηθείτε με τον target validator.
Ο validator σας θα πρέπει τώρα να επικοινωνεί μόνο με τους ρητά καταχωρισμένους validators και μόνο στις θύρες Gossip, Repair και ServeR.
Ρύθμιση Λογαριασμών Κατάθεσης
Οι λογαριασμοί Solana δεν απαιτούν καμία αρχικοποίηση onchain· μόλις περιέχουν κάποιο SOL, υπάρχουν. Για να ρυθμίσετε έναν λογαριασμό κατάθεσης για το ανταλλακτήριό σας, απλά δημιουργήστε ένα keypair Solana χρησιμοποιώντας οποιοδήποτε από τα εργαλεία πορτοφολιού μας.
Συνιστούμε τη χρήση μοναδικού λογαριασμού κατάθεσης για κάθε χρήστη σας.
Οι λογαριασμοί Solana πρέπει να γίνουν απαλλαγμένοι από rent περιέχοντας αξία 2 ετών σε rent σε SOL. Για να βρείτε το ελάχιστο υπόλοιπο απαλλαγής από rent για τους λογαριασμούς κατάθεσής σας, κάντε ερώτημα στο endpoint getMinimumBalanceForRentExemption:
curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id": 1,"method": "getMinimumBalanceForRentExemption","params": [0]}'
Αποτέλεσμα
{ "jsonrpc": "2.0", "result": 890880, "id": 1 }
Offline Λογαριασμοί
Ίσως επιθυμείτε να διατηρείτε τα κλειδιά για έναν ή περισσότερους λογαριασμούς συλλογής offline για μεγαλύτερη ασφάλεια. Σε αυτή την περίπτωση, θα πρέπει να μετακινείτε SOL σε hot λογαριασμούς χρησιμοποιώντας τις offline μεθόδους μας.
Παρακολούθηση Καταθέσεων
Όταν ένας χρήστης θέλει να καταθέσει SOL στο ανταλλακτήριό σας, δώστε του οδηγίες να στείλει μεταφορά στη διεύθυνση κατάθεσης που του αντιστοιχεί.
Μετάβαση σε Εκδοχές Συναλλαγών
Όταν το δίκτυο Mainnet αρχίσει να επεξεργάζεται εκδοχές συναλλαγών, τα ανταλλακτήρια ΠΡΕΠΕΙ να κάνουν αλλαγές. Εάν δεν γίνουν αλλαγές, η ανίχνευση καταθέσεων δεν θα λειτουργεί πλέον σωστά, διότι η ανάκτηση μιας εκδοχής συναλλαγής ή ενός block που περιέχει εκδοχές συναλλαγών θα επιστρέφει σφάλμα.
-
{"maxSupportedTransactionVersion": 0}Η παράμετρος
maxSupportedTransactionVersionπρέπει να προστεθεί στα αιτήματαgetBlockκαιgetTransactionγια να αποφευχθεί διακοπή στην ανίχνευση καταθέσεων. Η τελευταία έκδοση συναλλαγής είναι0και θα πρέπει να καθοριστεί ως η μέγιστη υποστηριζόμενη τιμή έκδοσης συναλλαγής.
Είναι σημαντικό να κατανοήσετε ότι οι εκδοχές συναλλαγών επιτρέπουν στους χρήστες να δημιουργούν συναλλαγές που χρησιμοποιούν ένα άλλο σύνολο κλειδιών λογαριασμού που φορτώνονται από onchain πίνακες αναζήτησης διευθύνσεων.
-
{"encoding": "jsonParsed"}Κατά την ανάκτηση block και συναλλαγών, συνιστάται πλέον η χρήση της κωδικοποίησης
"jsonParsed"διότι περιλαμβάνει όλα τα κλειδιά λογαριασμών συναλλαγής (συμπεριλαμβανομένων εκείνων από πίνακες αναζήτησης) στη λίστα"accountKeys"του μηνύματος. Αυτό καθιστά απλή την επίλυση αλλαγών υπολοίπου που αναφέρονται σταpreBalances/postBalancesκαιpreTokenBalances/postTokenBalances.Εάν χρησιμοποιείται η κωδικοποίηση
"json", οι εγγραφές σταpreBalances/postBalancesκαιpreTokenBalances/postTokenBalancesενδέχεται να αναφέρονται σε κλειδιά λογαριασμών που ΔΕΝ βρίσκονται στη λίστα"accountKeys"και πρέπει να επιλυθούν χρησιμοποιώντας εγγραφές"loadedAddresses"στα μεταδεδομένα της συναλλαγής.
Δημοσκόπηση για Block
Για να παρακολουθείτε όλους τους λογαριασμούς κατάθεσης του ανταλλακτηρίου σας, εκτελέστε δημοσκόπηση για κάθε επιβεβαιωμένο block και εξετάστε για διευθύνσεις ενδιαφέροντος, χρησιμοποιώντας την υπηρεσία JSON-RPC του κόμβου Solana API σας.
- Για να προσδιορίσετε ποια block είναι διαθέσιμα, στείλτε ένα αίτημα
getBlocks, περνώντας το τελευταίο block που έχετε ήδη επεξεργαστεί ως παράμετρο start-slot:
curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id": 1,"method": "getBlocks","params": [160017005, 160017015]}'
Αποτέλεσμα
{"jsonrpc": "2.0","result": [160017005, 160017006, 160017007, 160017012, 160017013, 160017014, 160017015],"id": 1}
Δεν παράγει block κάθε slot, οπότε ενδέχεται να υπάρχουν κενά στην ακολουθία των ακεραίων.
- Για κάθε block, ζητήστε τα περιεχόμενά του με ένα αίτημα
getBlock:
Συμβουλές Ανάκτησης Block
{"rewards": false}
Από προεπιλογή, τα ανακτώμενα block θα επιστρέφουν πληροφορίες σχετικά με τα τέλη validator σε κάθε block και τις ανταμοιβές staking στα όρια epoch. Εάν δεν χρειάζεστε αυτές τις πληροφορίες, απενεργοποιήστε τις με την παράμετρο "rewards".
{"transactionDetails": "accounts"}
Από προεπιλογή, τα ανακτώμενα block επιστρέφουν πολλές πληροφορίες συναλλαγών και μεταδεδομένα που δεν είναι απαραίτητα για την παρακολούθηση υπολοίπων λογαριασμών. Ορίστε την παράμετρο "transactionDetails" για να επιταχύνετε την ανάκτηση block.
curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' -d '{"jsonrpc": "2.0","id": 1,"method": "getBlock","params": [166974442,{"encoding": "jsonParsed","maxSupportedTransactionVersion": 0,"transactionDetails": "accounts","rewards": false}]}'
Αποτέλεσμα
{"jsonrpc": "2.0","result": {"blockHeight": 157201607,"blockTime": 1665070281,"blockhash": "HKhao674uvFc4wMK1Cm3UyuuGbKExdgPFjXQ5xtvsG3o","parentSlot": 166974441,"previousBlockhash": "98CNLU4rsYa2HDUyp7PubU4DhwYJJhSX9v6pvE7SWsAo","transactions": [... (omit){"meta": {"err": null,"fee": 5000,"postBalances": [1110663066,1,1040000000],"postTokenBalances": [],"preBalances": [1120668066,1,1030000000],"preTokenBalances": [],"status": {"Ok": null}},"transaction": {"accountKeys": [{"pubkey": "9aE476sH92Vz7DMPyq5WLPkrKWivxeuTKEFKd2sZZcde","signer": true,"source": "transaction","writable": true},{"pubkey": "11111111111111111111111111111111","signer": false,"source": "transaction","writable": false},{"pubkey": "G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o","signer": false,"source": "lookupTable","writable": true}],"signatures": ["2CxNRsyRT7y88GBwvAB3hRg8wijMSZh3VNYXAdUesGSyvbRJbRR2q9G1KSEpQENmXHmmMLHiXumw4dp8CvzQMjrM"]},"version": 0},... (omit)]},"id": 1}
Τα πεδία preBalances και postBalances σάς επιτρέπουν να παρακολουθείτε τις
αλλαγές υπολοίπου σε κάθε λογαριασμό χωρίς να χρειάζεται να αναλύσετε ολόκληρη τη συναλλαγή. Παραθέτουν τα αρχικά και τελικά υπόλοιπα κάθε λογαριασμού σε
lamports, με ευρετήριο στη λίστα accountKeys.
Για παράδειγμα, εάν η διεύθυνση κατάθεσης που σας ενδιαφέρει είναι
G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o, αυτή η συναλλαγή αντιπροσωπεύει μια
μεταφορά 1040000000 - 1030000000 = 10.000.000 lamports = 0,01 SOL
Εάν χρειάζεστε περισσότερες πληροφορίες σχετικά με τον τύπο συναλλαγής ή άλλες λεπτομέρειες, μπορείτε να ζητήσετε το block από το RPC σε δυαδική μορφή και να το αναλύσετε χρησιμοποιώντας είτε το Rust SDK είτε το Javascript SDK.
Ιστορικό Διεύθυνσης
Μπορείτε επίσης να αναζητήσετε το ιστορικό συναλλαγών μιας συγκεκριμένης διεύθυνσης. Αυτή η μέθοδος γενικά δεν είναι βιώσιμη για την παρακολούθηση όλων των διευθύνσεων κατάθεσής σας σε όλα τα slots, αλλά μπορεί να είναι χρήσιμη για την εξέταση μερικών λογαριασμών για μια συγκεκριμένη χρονική περίοδο.
- Στείλτε ένα αίτημα
getSignaturesForAddressστον κόμβο API:
curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id": 1,"method": "getSignaturesForAddress","params": ["3M2b3tLji7rvscqrLAHMukYxDK2nB96Q9hwfV6QkdzBN",{"limit": 3}]}'
Αποτέλεσμα
{"jsonrpc": "2.0","result": [{"blockTime": 1662064640,"confirmationStatus": "finalized","err": null,"memo": null,"signature": "3EDRvnD5TbbMS2mCusop6oyHLD8CgnjncaYQd5RXpgnjYUXRCYwiNPmXb6ZG5KdTK4zAaygEhfdLoP7TDzwKBVQp","slot": 148697216},{"blockTime": 1662064434,"confirmationStatus": "finalized","err": null,"memo": null,"signature": "4rPQ5wthgSP1kLdLqcRgQnkYkPAZqjv5vm59LijrQDSKuL2HLmZHoHjdSLDXXWFwWdaKXUuryRBGwEvSxn3TQckY","slot": 148696843},{"blockTime": 1662064341,"confirmationStatus": "finalized","err": null,"memo": null,"signature": "36Q383JMiqiobuPV9qBqy41xjMsVnQBm9rdZSdpbrLTGhSQDTGZJnocM4TQTVfUGfV2vEX9ZB3sex6wUBUWzjEvs","slot": 148696677}],"id": 1}
- Για κάθε υπογραφή που επιστρέφεται, λάβετε τις λεπτομέρειες της συναλλαγής στέλνοντας ένα
αίτημα
getTransaction:
curl https://api.devnet.solana.com -X POST -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":1,"method":"getTransaction","params":["2CxNRsyRT7y88GBwvAB3hRg8wijMSZh3VNYXAdUesGSyvbRJbRR2q9G1KSEpQENmXHmmMLHiXumw4dp8CvzQMjrM",{"encoding":"jsonParsed","maxSupportedTransactionVersion":0}]}'
Αποτέλεσμα
{"jsonrpc": "2.0","result": {"blockTime": 1665070281,"meta": {"err": null,"fee": 5000,"innerInstructions": [],"logMessages": ["Program 11111111111111111111111111111111 invoke [1]","Program 11111111111111111111111111111111 success"],"postBalances": [1110663066, 1, 1040000000],"postTokenBalances": [],"preBalances": [1120668066, 1, 1030000000],"preTokenBalances": [],"rewards": [],"status": {"Ok": null}},"slot": 166974442,"transaction": {"message": {"accountKeys": [{"pubkey": "9aE476sH92Vz7DMPyq5WLPkrKWivxeuTKEFKd2sZZcde","signer": true,"source": "transaction","writable": true},{"pubkey": "11111111111111111111111111111111","signer": false,"source": "transaction","writable": false},{"pubkey": "G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o","signer": false,"source": "lookupTable","writable": true}],"addressTableLookups": [{"accountKey": "4syr5pBaboZy4cZyF6sys82uGD7jEvoAP2ZMaoich4fZ","readonlyIndexes": [],"writableIndexes": [3]}],"instructions": [{"parsed": {"info": {"destination": "G1wZ113tiUHdSpQEBcid8n1x8BAvcWZoZgxPKxgE5B7o","lamports": 10000000,"source": "9aE476sH92Vz7DMPyq5WLPkrKWivxeuTKEFKd2sZZcde"},"type": "transfer"},"program": "system","programId": "11111111111111111111111111111111"}],"recentBlockhash": "BhhivDNgoy4L5tLtHb1s3TP19uUXqKiy4FfUR34d93eT"},"signatures": ["2CxNRsyRT7y88GBwvAB3hRg8wijMSZh3VNYXAdUesGSyvbRJbRR2q9G1KSEpQENmXHmmMLHiXumw4dp8CvzQMjrM"]},"version": 0},"id": 1}
Αποστολή Αναλήψεων
Για να ικανοποιήσετε το αίτημα ενός χρήστη για ανάληψη SOL, πρέπει να δημιουργήσετε μια συναλλαγή μεταφοράς Solana και να την αποστείλετε στον κόμβο API για να προωθηθεί στο cluster σας.
Σύγχρονη
Η αποστολή σύγχρονης μεταφοράς στο cluster Solana σάς επιτρέπει να διασφαλίσετε εύκολα ότι μια μεταφορά είναι επιτυχής και οριστικοποιημένη από το cluster.
Το εργαλείο γραμμής εντολών της Solana προσφέρει μια απλή εντολή, solana transfer, για
τη δημιουργία, υποβολή και επιβεβαίωση συναλλαγών μεταφοράς. Από προεπιλογή, αυτή η μέθοδος
θα αναμένει και θα παρακολουθεί την πρόοδο στο stderr μέχρι η συναλλαγή να οριστικοποιηθεί
από το cluster. Εάν η συναλλαγή αποτύχει, θα αναφέρει τυχόν σφάλματα συναλλαγής.
solana transfer <USER_ADDRESS> <AMOUNT> --allow-unfunded-recipient --keypair <KEYPAIR> --url http://localhost:8899
Το Solana Javascript SDK
προσφέρει παρόμοια προσέγγιση για το οικοσύστημα JS. Χρησιμοποιήστε το SystemProgram για να δημιουργήσετε
μια συναλλαγή μεταφοράς και υποβάλετέ την χρησιμοποιώντας τη μέθοδο sendAndConfirmTransaction.
Ασύγχρονη
Για μεγαλύτερη ευελιξία, μπορείτε να υποβάλετε μεταφορές ανάληψης ασύγχρονα. Σε αυτές τις περιπτώσεις, είναι δική σας ευθύνη να επαληθεύσετε ότι η συναλλαγή ήταν επιτυχής και οριστικοποιήθηκε από το cluster.
Σημείωση: Κάθε συναλλαγή περιέχει ένα πρόσφατο blockhash για να υποδεικνύει τη δραστηριότητά της. Είναι κρίσιμο να περιμένετε έως ότου λήξει αυτό το blockhash πριν επαναλάβετε μια μεταφορά ανάληψης που φαίνεται να μην έχει επιβεβαιωθεί ή οριστικοποιηθεί από το cluster. Διαφορετικά, κινδυνεύετε με διπλή δαπάνη. Δείτε περισσότερα για τη λήξη blockhash παρακάτω.
Αρχικά, λάβετε ένα πρόσφατο blockhash χρησιμοποιώντας το
endpoint getFees ή την εντολή CLI:
solana fees --url http://localhost:8899
Στο εργαλείο γραμμής εντολών, περάστε το όρισμα --no-wait για να αποστείλετε μια μεταφορά
ασύγχρονα, και συμπεριλάβετε το πρόσφατο blockhash σας με το όρισμα --blockhash:
solana transfer <USER_ADDRESS> <AMOUNT> --no-wait --allow-unfunded-recipient --blockhash <RECENT_BLOCKHASH> --keypair <KEYPAIR> --url http://localhost:8899
Μπορείτε επίσης να δημιουργήσετε, να υπογράψετε και να σειριοποιήσετε τη συναλλαγή χειροκίνητα, και να την αποστείλετε
στο cluster χρησιμοποιώντας το endpoint JSON-RPC
sendTransaction.
Επιβεβαιώσεις Συναλλαγής & Οριστικότητα
Λάβετε την κατάσταση μιας δέσμης συναλλαγών χρησιμοποιώντας το
JSON-RPC endpoint getSignatureStatuses.
Το πεδίο confirmations αναφέρει πόσα
επιβεβαιωμένα blocks έχουν παρέλθει
από τότε που επεξεργάστηκε η συναλλαγή. Εάν confirmations: null, είναι
οριστικοποιημένη.
curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{"jsonrpc":"2.0","id":1,"method":"getSignatureStatuses","params":[["4cdd1oX7cfVALfr26tP52BZ6cSzrgnNGtYD7BFhm6FFeZV5sPTnRvg6NRn8yC6DbEikXcrNChBM5vVJnTgKhGhVu","5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7"]]}'
Αποτέλεσμα
{"jsonrpc": "2.0","result": {"context": {"slot": 82},"value": [{"slot": 72,"confirmations": 10,"err": null,"status": {"Ok": null}},{"slot": 48,"confirmations": null,"err": null,"status": {"Ok": null}}]},"id": 1}
Λήξη Blockhash
Μπορείτε να ελέγξετε εάν ένα συγκεκριμένο blockhash εξακολουθεί να ισχύει στέλνοντας ένα αίτημα
getFeeCalculatorForBlockhash
με το blockhash ως παράμετρο. Εάν η τιμή απόκρισης είναι null, το
blockhash έχει λήξει και η συναλλαγή ανάληψης που χρησιμοποιεί αυτό το blockhash δεν θα πρέπει
ποτέ να επιτύχει.
Επικύρωση Διευθύνσεων Λογαριασμού που Παρέχονται από Χρήστες για Αναλήψεις
Καθώς οι αναλήψεις είναι μη αναστρέψιμες, μπορεί να είναι καλή πρακτική να επικυρώνετε μια διεύθυνση λογαριασμού που παρέχεται από χρήστη πριν εξουσιοδοτήσετε μια ανάληψη, ώστε να αποτρέψετε τυχαία απώλεια κεφαλαίων χρηστών.
Βασική επαλήθευση
Οι διευθύνσεις Solana είναι πίνακας 32 bytes, κωδικοποιημένος με το αλφάβητο bitcoin base58. Αυτό οδηγεί σε ένα αλφαριθμητικό ASCII που αντιστοιχεί στην ακόλουθη κανονική έκφραση:
[1-9A-HJ-NP-Za-km-z]{32,44}
Αυτός ο έλεγχος από μόνος του δεν επαρκεί, καθώς οι διευθύνσεις Solana δεν διαθέτουν άθροισμα ελέγχου, οπότε τα τυπογραφικά λάθη δεν μπορούν να εντοπιστούν. Για περαιτέρω επικύρωση της εισόδου του χρήστη, το αλφαριθμητικό μπορεί να αποκωδικοποιηθεί και το μήκος του προκύπτοντος πίνακα byte να επιβεβαιωθεί ότι είναι 32. Ωστόσο, υπάρχουν ορισμένες διευθύνσεις που μπορούν να αποκωδικοποιηθούν σε 32 bytes παρά ένα τυπογραφικό λάθος, όπως ένας μεμονωμένος χαρακτήρας που λείπει, αντεστραμμένοι χαρακτήρες και αγνοημένη πεζοκεφαλαία γραφή
Προηγμένη επαλήθευση
Λόγω της ευπάθειας σε τυπογραφικά λάθη που περιγράφηκε παραπάνω, συνιστάται να γίνεται ερώτημα υπολοίπου για τις υποψήφιες διευθύνσεις ανάληψης και να ζητείται από τον χρήστη να επιβεβαιώσει τις προθέσεις του εάν ανακαλυφθεί μη μηδενικό υπόλοιπο.
Έλεγχος έγκυρου pubkey ed25519
Η διεύθυνση ενός κανονικού λογαριασμού στη Solana είναι ένα αλφαριθμητικό κωδικοποιημένο σε Base58 ενός δημόσιου κλειδιού ed25519 256-bit. Δεν είναι όλα τα μοτίβα bit έγκυρα δημόσια κλειδιά για την καμπύλη ed25519, οπότε είναι δυνατόν να διασφαλιστεί ότι οι διευθύνσεις λογαριασμού που παρέχονται από χρήστες είναι τουλάχιστον σωστά δημόσια κλειδιά ed25519.
Java
Ακολουθεί ένα παράδειγμα Java για την επικύρωση μιας διεύθυνσης που παρέχεται από χρήστη ως έγκυρο δημόσιο κλειδί ed25519:
Το παρακάτω δείγμα κώδικα προϋποθέτει ότι χρησιμοποιείτε το Maven.
pom.xml:
<repositories>...<repository><id>spring</id><url>https://repo.spring.io/libs-release/</url></repository></repositories>...<dependencies>...<dependency><groupId>io.github.novacrypto</groupId><artifactId>Base58</artifactId><version>0.1.3</version></dependency><dependency><groupId>cafe.cryptography</groupId><artifactId>curve25519-elisabeth</artifactId><version>0.1.0</version></dependency><dependencies>
import io.github.novacrypto.base58.Base58;import cafe.cryptography.curve25519.CompressedEdwardsY;public class PubkeyValidator{public static boolean verifyPubkey(String userProvidedPubkey){try {return _verifyPubkeyInternal(userProvidedPubkey);} catch (Exception e) {return false;}}public static boolean _verifyPubkeyInternal(String maybePubkey) throws Exception{byte[] bytes = Base58.base58Decode(maybePubkey);return !(new CompressedEdwardsY(bytes)).decompress().isSmallOrder();}}
Ελάχιστα Ποσά Κατάθεσης & Ανάληψης
Κάθε κατάθεση και ανάληψη SOL πρέπει να είναι μεγαλύτερη ή ίση με το ελάχιστο υπόλοιπο απαλλαγής ενοικίου για τον λογαριασμό στη διεύθυνση πορτοφολιού (ένας βασικός λογαριασμός SOL χωρίς δεδομένα), αυτή τη στιγμή: 0,000890880 SOL
Ομοίως, κάθε λογαριασμός κατάθεσης πρέπει να περιέχει τουλάχιστον αυτό το υπόλοιπο.
curl https://api.devnet.solana.com -X POST -H "Content-Type: application/json" -d '{"jsonrpc": "2.0","id": 1,"method": "getMinimumBalanceForRentExemption","params": [0]}'
Αποτέλεσμα
{ "jsonrpc": "2.0", "result": 890880, "id": 1 }
Τέλη Προτεραιότητας και Μονάδες Υπολογισμού
Σε περιόδους υψηλής ζήτησης, είναι πιθανό μια συναλλαγή να λήξει πριν ένας validator την συμπεριλάβει στο block του, επειδή επέλεξε άλλες συναλλαγές με υψηλότερη οικονομική αξία. Έγκυρες συναλλαγές στη Solana ενδέχεται να καθυστερήσουν ή να απορριφθούν εάν τα Τέλη Προτεραιότητας δεν εφαρμοστούν σωστά.
Τα Τέλη Προτεραιότητας είναι πρόσθετα τέλη που μπορούν να προστεθούν πάνω από το βασικό Τέλος Συναλλαγής για να διασφαλιστεί η συμπερίληψη συναλλαγής εντός των blocks σε αυτές τις καταστάσεις και να βοηθήσουν στη διασφάλιση της παραδοσιμότητας.
Αυτά τα τέλη προτεραιότητας προστίθενται στη συναλλαγή με την προσθήκη μιας ειδικής εντολής Compute Budget που ορίζει το επιθυμητό τέλος προτεραιότητας προς καταβολή.
Σημαντική Σημείωση
Η μη εφαρμογή αυτών των οδηγιών ενδέχεται να οδηγήσει σε διαταραχές δικτύου και απορριφθείσες συναλλαγές. Συνιστάται ανεπιφύλακτα σε κάθε ανταλλακτήριο που υποστηρίζει Solana να χρησιμοποιεί τέλη προτεραιότητας για την αποφυγή διαταραχών.
Τι είναι ένα Τέλος Προτεραιότητας;
Τα Τέλη Προτεραιότητας τιμολογούνται σε micro-lamports ανά Μονάδα Υπολογισμού (π.χ. μικρά ποσά SOL) που προτάσσονται στις συναλλαγές για να τις καταστήσουν οικονομικά ελκυστικές για τους κόμβους validator ώστε να τις συμπεριλαμβάνουν στα blocks του δικτύου.
Πόσο πρέπει να είναι το Τέλος Προτεραιότητας;
Η μέθοδος για τον ορισμό του τέλους προτεραιότητάς σας θα πρέπει να περιλαμβάνει αναζήτηση πρόσφατων
τελών προτεραιότητας για τον καθορισμό ενός τέλους που είναι πιθανό να είναι ελκυστικό για το
δίκτυο. Χρησιμοποιώντας τη μέθοδο RPC
getRecentPrioritizationFees,
μπορείτε να αναζητήσετε τα τέλη προτεραιότητας που απαιτούνται για να καταχωριστεί μια συναλλαγή
σε ένα πρόσφατο block.
Η στρατηγική τιμολόγησης για αυτά τα τέλη προτεραιότητας θα ποικίλλει ανάλογα με την περίπτωση χρήσης σας. Δεν υπάρχει κανονικός τρόπος για να γίνει αυτό. Μια στρατηγική για τον καθορισμό των Τελών Προτεραιότητάς σας θα μπορούσε να είναι ο υπολογισμός του ποσοστού επιτυχίας των συναλλαγών σας και στη συνέχεια η αύξηση του Τέλους Προτεραιότητάς σας σε σχέση με ένα ερώτημα στο API πρόσφατων τελών συναλλαγών και η ανάλογη προσαρμογή. Η τιμολόγηση για τα Τέλη Προτεραιότητας θα είναι δυναμική βάσει της δραστηριότητας στο δίκτυο και των προσφορών άλλων συμμετεχόντων, γνωστή μόνο εκ των υστέρων.
Μια πρόκληση με τη χρήση της κλήσης API getRecentPrioritizationFees είναι ότι
μπορεί να επιστρέφει μόνο το χαμηλότερο τέλος για κάθε block. Αυτό συχνά θα είναι μηδέν, πράγμα που
δεν αποτελεί πλήρως χρήσιμη προσέγγιση για το ποιο Τέλος Προτεραιότητας να χρησιμοποιηθεί προκειμένου
να αποφευχθεί η απόρριψη από κόμβους validator.
Το API getRecentPrioritizationFees δέχεται pubkeys λογαριασμών ως παραμέτρους και
επιστρέφει το υψηλότερο από τα ελάχιστα τέλη προτεραιότητας για αυτούς τους λογαριασμούς.
Όταν δεν έχει καθοριστεί λογαριασμός, το API θα επιστρέψει το χαμηλότερο τέλος για καταχώριση στο
block, το οποίο συνήθως είναι μηδέν (εκτός εάν το block είναι πλήρες).
Τα ανταλλακτήρια και οι εφαρμογές θα πρέπει να αναζητούν το RPC endpoint με τους λογαριασμούς στους
οποίους μια συναλλαγή πρόκειται να εφαρμόσει write-lock. Το RPC endpoint θα επιστρέψει το
max(account_1_min_fee, account_2_min_fee, ... account_n_min_fee), το οποίο θα πρέπει
να είναι το σημείο βάσης για τον χρήστη για να ορίσει το τέλος προτεραιότητας για εκείνη τη
συναλλαγή.
Υπάρχουν διαφορετικές προσεγγίσεις για τον καθορισμό Τελών Προτεραιότητας και ορισμένα API τρίτων είναι διαθέσιμα για τον προσδιορισμό του βέλτιστου τέλους προς εφαρμογή. Δεδομένης της δυναμικής φύσης του δικτύου, δεν θα υπάρχει ένας "τέλειος" τρόπος για την τιμολόγηση των Τελών Προτεραιότητάς σας και πρέπει να εφαρμοστεί προσεκτική ανάλυση πριν από την επιλογή μιας πορείας.
Πώς να Υλοποιήσετε Τέλη Προτεραιότητας
Η προσθήκη τελών προτεραιότητας σε μια συναλλαγή συνίσταται στην πρόταξη δύο εντολών Compute Budget σε μια δεδομένη συναλλαγή:
- μία για τον ορισμό της τιμής μονάδας υπολογισμού, και
- μία άλλη για τον ορισμό του ορίου μονάδας υπολογισμού
Εδώ, μπορείτε επίσης να βρείτε έναν πιο λεπτομερή οδηγό για προγραμματιστές σχετικά με τη χρήση τελών προτεραιότητας που περιλαμβάνει περισσότερες πληροφορίες σχετικά με την υλοποίηση τελών προτεραιότητας.
Δημιουργήστε μια εντολή setComputeUnitPrice για να προσθέσετε ένα Τέλος Προτεραιότητας πάνω από το
Βασικό Τέλος Συναλλαγής (5.000 Lamports).
// import { ComputeBudgetProgram } from "@solana/web3.js"ComputeBudgetProgram.setComputeUnitPrice({ microLamports: number });
Η τιμή που παρέχεται σε micro-lamports θα πολλαπλασιαστεί με τον προϋπολογισμό Μονάδων Υπολογισμού (CU)
για να προσδιοριστεί το Τέλος Προτεραιότητας σε Lamports. Για παράδειγμα, εάν ο προϋπολογισμός CU σας
είναι 1M CU και προσθέτετε 1 microLamport/CU, το Τέλος Προτεραιότητας θα είναι
1 lamport (1M * 0. 000001). Το συνολικό τέλος θα είναι τότε 5001 lamports.
Για να ορίσετε νέο όριο μονάδων υπολογισμού για τη συναλλαγή, δημιουργήστε μια
εντολή setComputeUnitLimit
// import { ComputeBudgetProgram } from "@solana/web3.js"ComputeBudgetProgram.setComputeUnitLimit({ units: number });
Η τιμή units που παρέχεται θα αντικαταστήσει την προεπιλεγμένη τιμή προϋπολογισμού υπολογισμού του χρόνου εκτέλεσης Solana.
Ορίστε τις ελάχιστες απαιτούμενες CU για τη συναλλαγή
Οι συναλλαγές θα πρέπει να ζητούν την ελάχιστη ποσότητα μονάδων υπολογισμού (CU) που απαιτείται για εκτέλεση ώστε να μεγιστοποιηθεί η ροή εργασίας και να ελαχιστοποιηθούν τα συνολικά τέλη.
Μπορείτε να λάβετε τις CU που καταναλώνει μια συναλλαγή αποστέλλοντάς την σε ένα διαφορετικό cluster Solana, όπως το devnet. Για παράδειγμα, μια απλή μεταφορά token χρειάζεται 300 CU.
// import { ... } from "@solana/web3.js"const modifyComputeUnits = ComputeBudgetProgram.setComputeUnitLimit({// note: set this to be the lowest actual CU consumed by the transactionunits: 300});const addPriorityFee = ComputeBudgetProgram.setComputeUnitPrice({microLamports: 1});const transaction = new Transaction().add(modifyComputeUnits).add(addPriorityFee).add(SystemProgram.transfer({fromPubkey: payer.publicKey,toPubkey: toAccount,lamports: 10000000}));
Τέλη Προτεραιότητας και Ανθεκτικά Nonces
Εάν η ρύθμισή σας χρησιμοποιεί Durable Nonce Transactions, είναι σημαντικό να υλοποιήσετε σωστά τα Prioritization Fees σε συνδυασμό με τα Durable Transaction Nonces για να διασφαλίσετε επιτυχημένες συναλλαγές. Η αποτυχία να το κάνετε αυτό θα προκαλέσει οι προβλεπόμενες Durable Nonce συναλλαγές να μην αναγνωρίζονται ως τέτοιες.
Εάν ΧΡΗΣΙΜΟΠΟΙΕΙΤΕ Durable Transaction Nonces, η εντολή AdvanceNonceAccount
ΠΡΕΠΕΙ να καθορίζεται ΠΡΩΤΗ στη λίστα εντολών, ακόμα και όταν
χρησιμοποιούνται εντολές compute budget για τον καθορισμό priority fees.
Μπορείτε να βρείτε ένα συγκεκριμένο παράδειγμα κώδικα χρησιμοποιώντας durable nonces και priority fees μαζί σε αυτόν τον οδηγό για προγραμματιστές.
Υποστήριξη του Προτύπου SPL Token
Το SPL Token είναι το πρότυπο για τη δημιουργία και ανταλλαγή wrapped/synthetic token στο blockchain Solana.
Η ροή εργασίας του SPL Token είναι παρόμοια με αυτή των native SOL tokens, αλλά υπάρχουν μερικές διαφορές που θα συζητηθούν σε αυτή την ενότητα.
Token Mints
Κάθε τύπος SPL Token δηλώνεται με τη δημιουργία ενός mint account. Αυτό το account αποθηκεύει μεταδεδομένα που περιγράφουν χαρακτηριστικά token όπως την προσφορά, τον αριθμό των δεκαδικών, και διάφορες αρχές με έλεγχο πάνω στο mint. Κάθε SPL Token account αναφέρεται στο συσχετισμένο mint του και μπορεί να αλληλεπιδρά μόνο με SPL Tokens αυτού του τύπου.
Εγκατάσταση του Εργαλείου CLI spl-token
Τα SPL Token accounts γίνονται αναζήτηση και τροποποίηση χρησιμοποιώντας το βοηθητικό πρόγραμμα γραμμής εντολών spl-token. Τα παραδείγματα που παρέχονται σε αυτή την ενότητα απαιτούν να είναι εγκατεστημένο
στο τοπικό σύστημα.
Το spl-token διανέμεται από το Rust
crates.io μέσω του βοηθητικού προγράμματος γραμμής εντολών cargo της Rust.
Η τελευταία έκδοση του cargo μπορεί να εγκατασταθεί χρησιμοποιώντας ένα εύχρηστο
one-liner για την πλατφόρμα σας στο rustup.rs. Μόλις εγκατασταθεί το cargo,
το spl-token μπορεί να αποκτηθεί με την παρακάτω εντολή:
cargo install spl-token-cli
Στη συνέχεια μπορείτε να ελέγξετε την εγκατεστημένη έκδοση για επαλήθευση
spl-token --version
Το οποίο θα πρέπει να δώσει αποτέλεσμα παρόμοιο με
spl-token-cli 2.0.1
Δημιουργία Λογαριασμού
Τα SPL Token accounts φέρουν πρόσθετες απαιτήσεις που τα native System Program accounts δεν έχουν:
- Τα SPL Token accounts πρέπει να δημιουργηθούν πριν μπορέσει να
κατατεθεί ποσό tokens. Τα token accounts μπορούν να δημιουργηθούν ρητά με την
εντολή
spl-token create-account, ή σιωπηρά με την εντολήspl-token transfer --fund-recipient .... - Τα SPL Token accounts πρέπει να παραμένουν απαλλαγμένα από ενοίκιο για τη διάρκεια της ύπαρξής τους και επομένως απαιτούν να κατατεθεί ένα μικρό ποσό native SOL tokens κατά τη δημιουργία του λογαριασμού. Για τα SPL Token accounts, αυτό το ποσό είναι 0,00203928 SOL (2.039.280 lamports).
Γραμμή Εντολών
Για να δημιουργήσετε ένα SPL Token account με τις παρακάτω ιδιότητες:
- Συσχετισμένο με το δεδομένο mint
- Ανήκει στο keypair του λογαριασμού χρηματοδότησης
spl-token create-account <TOKEN_MINT_ADDRESS>
Παράδειγμα
spl-token create-account AkUFCWTXb3w9nY2n6SFJvBV6VwvFUCe4KBMCcgLsa2ir
Δίνοντας αποτέλεσμα παρόμοιο με:
Creating account 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkVSignature: 4JsqZEPra2eDTHtHpB4FMWSfk3UgcCVmkKkP7zESZeMrKmFFkDkNd91pKP3vPVVZZPiu5XxyJwS73Vi5WsZL88D7
Ή για να δημιουργήσετε ένα SPL Token account με συγκεκριμένο keypair:
solana-keygen new -o token-account.jsonspl-token create-account AkUFCWTXb3w9nY2n6SFJvBV6VwvFUCe4KBMCcgLsa2ir token-account.json
Δίνοντας αποτέλεσμα παρόμοιο με:
Creating account 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkVSignature: 4JsqZEPra2eDTHtHpB4FMWSfk3UgcCVmkKkP7zESZeMrKmFFkDkNd91pKP3vPVVZZPiu5XxyJwS73Vi5WsZL88D7
Έλεγχος Υπολοίπου Λογαριασμού
Γραμμή Εντολών
spl-token balance <TOKEN_ACCOUNT_ADDRESS>
Παράδειγμα
solana balance 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkV
Δίνοντας αποτέλεσμα παρόμοιο με:
0
Μεταφορές Token
Ο λογαριασμός πηγής για μια μεταφορά είναι το πραγματικό token account που περιέχει το ποσό.
Ωστόσο, η διεύθυνση παραλήπτη μπορεί να είναι ένας κανονικός λογαριασμός πορτοφολιού. Εάν ένα associated
token account για το δεδομένο mint δεν υπάρχει ακόμα για αυτό το πορτοφόλι, η
μεταφορά θα το δημιουργήσει υπό την προϋπόθεση ότι παρέχεται το όρισμα --fund-recipient.
Γραμμή Εντολών
spl-token transfer <SENDER_ACCOUNT_ADDRESS> <AMOUNT> <RECIPIENT_WALLET_ADDRESS> --fund-recipient
Παράδειγμα
spl-token transfer 6B199xxzw3PkAm25hGJpjj3Wj3WNYNHzDAnt1tEqg5BN 1
Δίνοντας αποτέλεσμα παρόμοιο με:
6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkVTransfer 1 tokensSender: 6B199xxzw3PkAm25hGJpjj3Wj3WNYNHzDAnt1tEqg5BNRecipient: 6VzWGL51jLebvnDifvcuEDec17sK6Wupi4gYhm5RzfkVSignature: 3R6tsog17QM8KfzbcbdP4aoMfwgo6hBggJDVy7dZPVmH2xbCWjEj31JKD53NzMrf25ChFjY7Uv2dfCDq4mGFFyAj
Κατάθεση
Εφόσον κάθε ζεύγος (wallet, mint) απαιτεί ξεχωριστό λογαριασμό onchain, συνιστάται
οι διευθύνσεις για αυτούς τους λογαριασμούς να προέρχονται από πορτοφόλια κατάθεσης SOL
χρησιμοποιώντας το σχήμα
Associated Token Account
(ATA) και να γίνονται δεκτές μόνο καταθέσεις από διευθύνσεις ATA.
Η παρακολούθηση για συναλλαγές κατάθεσης θα πρέπει να ακολουθεί τη μέθοδο block polling που περιγράφεται παραπάνω. Κάθε νέο block θα πρέπει να σαρώνεται για επιτυχημένες συναλλαγές που περιλαμβάνουν τις διευθύνσεις token account του χρήστη και του ανταλλακτηρίου.
Τα πεδία preTokenBalances και postTokenBalances από τα
μεταδεδομένα της συναλλαγής πρέπει να χρησιμοποιούνται για τον προσδιορισμό της πραγματικής μεταβολής υπολοίπου. Αυτά τα πεδία
περιλαμβάνουν το token mint, τον ιδιοκτήτη του token account (διεύθυνση πορτοφολιού) και τα υπόλοιπα
των token accounts πριν και μετά τη συναλλαγή.
Εάν ένα token account δημιουργηθεί ως μέρος μιας συναλλαγής (όπως όταν λαμβάνονται
tokens για πρώτη φορά), δεν θα εμφανιστεί στον πίνακα preTokenBalances
καθώς δεν υπήρχε πριν από τη συναλλαγή. Σε αυτό το σενάριο, θα πρέπει να αντιμετωπίζετε
το αρχικό υπόλοιπο ως μηδέν κατά τον υπολογισμό ποσών κατάθεσης. Ο νεοδημιουργηθείς
λογαριασμός θα εμφανίζεται μόνο στον πίνακα postTokenBalances με το τελικό του υπόλοιπο
μετά την ολοκλήρωση της συναλλαγής.
Παράδειγμα 1: Μονή Μεταφορά Token
Η παρακάτω λεπτομέρεια συναλλαγής δείχνει ένα παράδειγμα συναλλαγής που περιλαμβάνει μία μόνο εντολή μεταφοράς token.
Η συναλλαγή μεταφέρει 100 βασικές μονάδες του token (μη προσαρμοσμένες για τα δεκαδικά του mint) και περιλαμβάνει τους παρακάτω λογαριασμούς:
- Αποστολέας (ιδιοκτήτης):
4fvXFPXSL9i7VbiRzoizuW4bhn1dMvRgQzQ6VevssYxw - Token Account Αποστολέα:
6zhjktfYBRUp7fgXLoWU7GFFrCuZa9iQkYTQzDzuvsAS - Token Account Παραλήπτη:
G5nNekUhhWFqJAiCMpKHootZ5Bfa7MXwuQ5vvKcvuxKM - Token Extension Program ID:
TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
Σημειώστε ότι ο λογαριασμός παραλήπτη (ιδιοκτήτης) και το mint account δεν απαιτούνται σε μια εντολή μεταφοράς token. Για αναφορά, παρατίθενται εδώ καθώς οι διευθύνσεις περιλαμβάνονται στα αναλυμένα μεταδεδομένα της συναλλαγής.
- Παραλήπτης (ιδιοκτήτης):
8fjS2shNWY8xniiEMLNk1Aek4MAu8Qp2LCXJckVwTD4n - Mint:
Fx1JZFeYbCxLrMv7422YSxpr7YzcsAgpU1MkjZTyCKi2
{"blockTime": "1741240211","meta": {"computeUnitsConsumed": "1551","err": null,"fee": "5000","innerInstructions": [],"loadedAddresses": {"readonly": [],"writable": []},"logMessages": ["Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [1]","Program log: Instruction: Transfer","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1551 of 200000 compute units","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success"],"postBalances": ["994375240", "2074080", "2074080", "1141440"],"postTokenBalances": [{"accountIndex": 1,"mint": "Fx1JZFeYbCxLrMv7422YSxpr7YzcsAgpU1MkjZTyCKi2","owner": "4fvXFPXSL9i7VbiRzoizuW4bhn1dMvRgQzQ6VevssYxw","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "0","decimals": 2,"uiAmount": null,"uiAmountString": "0"}},{"accountIndex": 2,"mint": "Fx1JZFeYbCxLrMv7422YSxpr7YzcsAgpU1MkjZTyCKi2","owner": "8fjS2shNWY8xniiEMLNk1Aek4MAu8Qp2LCXJckVwTD4n","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "100","decimals": 2,"uiAmount": "1","uiAmountString": "1"}}],"preBalances": ["994380240", "2074080", "2074080", "1141440"],"preTokenBalances": [{"accountIndex": 1,"mint": "Fx1JZFeYbCxLrMv7422YSxpr7YzcsAgpU1MkjZTyCKi2","owner": "4fvXFPXSL9i7VbiRzoizuW4bhn1dMvRgQzQ6VevssYxw","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "100","decimals": 2,"uiAmount": "1","uiAmountString": "1"}},{"accountIndex": 2,"mint": "Fx1JZFeYbCxLrMv7422YSxpr7YzcsAgpU1MkjZTyCKi2","owner": "8fjS2shNWY8xniiEMLNk1Aek4MAu8Qp2LCXJckVwTD4n","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "0","decimals": 2,"uiAmount": null,"uiAmountString": "0"}}],"rewards": [],"status": {"Ok": null}},"slot": "3916","transaction": {"message": {"accountKeys": ["4fvXFPXSL9i7VbiRzoizuW4bhn1dMvRgQzQ6VevssYxw","6zhjktfYBRUp7fgXLoWU7GFFrCuZa9iQkYTQzDzuvsAS","G5nNekUhhWFqJAiCMpKHootZ5Bfa7MXwuQ5vvKcvuxKM","TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"],"addressTableLookups": [],"header": {"numReadonlySignedAccounts": 0,"numReadonlyUnsignedAccounts": 1,"numRequiredSignatures": 1},"instructions": [{"accounts": [1, 2, 0],"data": "3WBgs5fm8oDy","programIdIndex": 3,"stackHeight": null}],"recentBlockhash": "8soh8j2dkEniZW6Jpx9cJaWtnvrGoGUqpbaUVwUkX5R3"},"signatures": ["3vr6Gj3GnBQmsZW1TtBJ3hvfFMi3h9BxLs2oaZkV41LRWeGWPVmeo16JTN8MdP3ypU5VgWAziYUjybhyZoisryQ6"]},"version": "0"}
Παράδειγμα 2: Δημιουργία Token Account και Μεταφορά
Η παρακάτω λεπτομέρεια συναλλαγής δείχνει ένα παράδειγμα συναλλαγής όπου το token account του παραλήπτη δημιουργείται στην ίδια συναλλαγή με τη μεταφορά token.
Σημειώστε ότι ο πίνακας preTokenBalances δεν περιλαμβάνει το token account του παραλήπτη
καθώς δεν υπήρχε πριν από τη συναλλαγή. Το token account του παραλήπτη
εμφανίζεται μόνο στον πίνακα postTokenBalances με το τελικό του υπόλοιπο
μετά την ολοκλήρωση της συναλλαγής.
{"blockTime": "1740541705","meta": {"computeUnitsConsumed": "17416","err": null,"fee": "5000","innerInstructions": [{"index": 0,"instructions": [{"accounts": [4],"data": "84eT","programIdIndex": 7,"stackHeight": 2},{"accounts": [0, 1],"data": "11119ExAoTptm6xKUTUcw2V69MKmyEdDmRins3j3bK43o9nHeiYUtSiaT9pc292PhNQvxj","programIdIndex": 3,"stackHeight": 2},{"accounts": [1],"data": "P","programIdIndex": 7,"stackHeight": 2},{"accounts": [1, 4],"data": "6b8ZSccu4ezujyhGG8KNmg75iCWbQRyjxeSfi38u8ED8N","programIdIndex": 7,"stackHeight": 2}]}],"loadedAddresses": {"readonly": [],"writable": []},"logMessages": ["Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL invoke [1]","Program log: Create","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]","Program log: Instruction: GetAccountDataSize","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 928 of 394613 compute units","Program return: TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb qgAAAAAAAAA=","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success","Program 11111111111111111111111111111111 invoke [2]","Program 11111111111111111111111111111111 success","Program log: Initialize the associated token account","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]","Program log: Instruction: InitializeImmutableOwner","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 487 of 388755 compute units","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [2]","Program log: Instruction: InitializeAccount3","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1440 of 385879 compute units","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success","Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL consumed 15865 of 400000 compute units","Program ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL success","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [1]","Program log: Instruction: Transfer","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1551 of 384135 compute units","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success"],"postBalances": ["994375240","2074080","2074080","1","1461600","731913600","0","1141440"],"postTokenBalances": [{"accountIndex": 1,"mint": "3RPRXBsdwyHhs2UnTWXoHp6Frwv4eWEbA55qCzbs9nxK","owner": "EzrmgRNGN9duiDAk3ABSC8eKhd1b2EUFwXVrYZDJw4hQ","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "100","decimals": 2,"uiAmount": "1","uiAmountString": "1"}},{"accountIndex": 2,"mint": "3RPRXBsdwyHhs2UnTWXoHp6Frwv4eWEbA55qCzbs9nxK","owner": "CbJNxBnU9ZWnQq12aVHhbze9nubbDVDV5rYVEqz9qFaS","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "0","decimals": 2,"uiAmount": null,"uiAmountString": "0"}}],"preBalances": ["996454320","0","2074080","1","1461600","731913600","0","1141440"],"preTokenBalances": [{"accountIndex": 2,"mint": "3RPRXBsdwyHhs2UnTWXoHp6Frwv4eWEbA55qCzbs9nxK","owner": "CbJNxBnU9ZWnQq12aVHhbze9nubbDVDV5rYVEqz9qFaS","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "100","decimals": 2,"uiAmount": "1","uiAmountString": "1"}}],"rewards": [],"status": {"Ok": null}},"slot": "81051","transaction": {"message": {"accountKeys": ["CbJNxBnU9ZWnQq12aVHhbze9nubbDVDV5rYVEqz9qFaS","571u96hRRmxbRCTmp5oqC5WpJfvZhPaSXEbihLVCR5wQ","8y8KjtZN9tyGeAeKwr8doSpbBVVgfsZMtMjCGUDH7mmU","11111111111111111111111111111111","3RPRXBsdwyHhs2UnTWXoHp6Frwv4eWEbA55qCzbs9nxK","ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL","EzrmgRNGN9duiDAk3ABSC8eKhd1b2EUFwXVrYZDJw4hQ","TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"],"addressTableLookups": [],"header": {"numReadonlySignedAccounts": 0,"numReadonlyUnsignedAccounts": 5,"numRequiredSignatures": 1},"instructions": [{"accounts": [0, 1, 6, 4, 3, 7],"data": "1","programIdIndex": 5,"stackHeight": null},{"accounts": [2, 1, 0],"data": "3WBgs5fm8oDy","programIdIndex": 7,"stackHeight": null}],"recentBlockhash": "77QC38Q2hKFYZzUXk8JWmsAqGNKhw4k2Lm2XVUme9uqP"},"signatures": ["4kuGhMeZxBHgEtej4Uv4n2arhe3jqT2GdTDPFri4JLFXYgcAtbeeXdBdzvG98HENe1tZSZqyFkm3SEvB6CfCMaM9"]},"version": "0"}
Παράδειγμα 3: Αλλαγή Ιδιοκτήτη Token Account
Η παρακάτω λεπτομέρεια συναλλαγής δείχνει ένα παράδειγμα συναλλαγής όπου το πεδίο owner
του token account αλλάζει.
Η αποδοχή καταθέσεων επιτρέποντας στους καταθέτες να μεταβιβάζουν την ιδιοκτησία token accounts
(αλλάζοντας το πεδίο owner) αποθαρρύνεται έντονα.
Εάν επιλέξετε να υποστηρίξετε αυτό ως μέθοδο κατάθεσης, πρέπει να επαληθεύσετε ότι το νέο
πεδίο owner στα postTokenBalances αντιστοιχεί σε μια διεύθυνση πορτοφολιού που ελέγχει
το ανταλλακτήριό σας και για την οποία διαθέτετε το ιδιωτικό κλειδί.
Εάν ένας καταθέτης αλλάξει τον owner ενός token account σε μια διεύθυνση που δεν
είναι πορτοφόλι (όπως μια άλλη διεύθυνση token account), τα κεφάλαια ενδέχεται να καταστούν
μόνιμα μη προσβάσιμα.
{"blockTime": "1740598556","meta": {"computeUnitsConsumed": "1167","err": null,"fee": "5000","innerInstructions": [],"loadedAddresses": {"readonly": [],"writable": []},"logMessages": ["Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb invoke [1]","Program log: Instruction: SetAuthority","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb consumed 1167 of 200000 compute units","Program TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb success"],"postBalances": ["996479120", "2039280", "1141440"],"postTokenBalances": [{"accountIndex": 1,"mint": "ELRBdV4gcuxqYb6jHkV4ySJ7dwYx9344cgFNzUSww1ra","owner": "A9FK8XxT2Hfefz8H3vQJHLwvbibGQJWErBsqMumgUYeP","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "100","decimals": 2,"uiAmount": "1","uiAmountString": "1"}}],"preBalances": ["996484120", "2039280", "1141440"],"preTokenBalances": [{"accountIndex": 1,"mint": "ELRBdV4gcuxqYb6jHkV4ySJ7dwYx9344cgFNzUSww1ra","owner": "DLvpDgEABKfEaRDz5Qh9tSrJhuZzsiiZMcYXmvdek1zV","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "100","decimals": 2,"uiAmount": "1","uiAmountString": "1"}}],"rewards": [],"status": {"Ok": null}},"slot": "137902","transaction": {"message": {"accountKeys": ["DLvpDgEABKfEaRDz5Qh9tSrJhuZzsiiZMcYXmvdek1zV","5Qj4uNGuAEBdryPg8k2UTewpnNfYAc9Ux9fCcDrNAjGs","TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb"],"addressTableLookups": [],"header": {"numReadonlySignedAccounts": 0,"numReadonlyUnsignedAccounts": 1,"numRequiredSignatures": 1},"instructions": [{"accounts": [1, 0],"data": "bmb6sys4wqZErNeiV7hrM4vQVHF8AVBhi3XeR5TgbQM68MH","programIdIndex": 2,"stackHeight": null}],"recentBlockhash": "CvTdX9MSYkqFMkALUHeGPMQN5yBeUdJptRdce2qMEkPr"},"signatures": ["3rHUaKMh4KDDfdaATAL4J5WDEV7oFm7ykkNaMf1Eo5EwvDUjLE6dWsbxNDmyENrhb2w5gE4KqRxZ3ZwQxuM18SVR"]},"version": "0"}
Υπολογισμός Κατάθεσης Token
Για την ακριβή παρακολούθηση καταθέσεων token, πρέπει να συγκρίνετε τα πεδία preTokenBalances και
postTokenBalance στα μεταδεδομένα της συναλλαγής. Αυτά τα πεδία δείχνουν τα
υπόλοιπα token και τον ιδιοκτήτη του token account πριν και μετά τη συναλλαγή,
επιτρέποντάς σας να υπολογίσετε το ακριβές ποσό των tokens που μεταφέρθηκαν. Αυτή η προσέγγιση
διασφαλίζει ότι καταγράφετε τις πραγματικές μεταβολές υπολοίπου.
- Εάν το πεδίο
ownerτων πεδίωνpreTokenBalancesκαιpostTokenBalancesπαραμένει το ίδιο, υπολογίστε τη διαφορά μεταξύ των πεδίωνamount. - Εάν η ιδιοκτησία του token account αλλάζει (διαφορετικό πεδίο
ownerμεταξύpreTokenBalancesκαιpostTokenBalances), και ο νέος ιδιοκτήτης στοpostTokenBalanceταιριάζει με την αναμενόμενη διεύθυνσηownerτου ανταλλακτηρίου σας, τότε θεωρήστε ολόκληρο το υπόλοιπο που εμφανίζεται στο πεδίοamountτωνpostTokenBalancesως το κατατεθειμένο ποσό.
"meta": {// --snip--"postBalances": ["994375240", "2074080", "2074080", "1141440"],"postTokenBalances": [{"accountIndex": 1,"mint": "Fx1JZFeYbCxLrMv7422YSxpr7YzcsAgpU1MkjZTyCKi2","owner": "4fvXFPXSL9i7VbiRzoizuW4bhn1dMvRgQzQ6VevssYxw","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "0","decimals": 2,"uiAmount": null,"uiAmountString": "0"}},{"accountIndex": 2,"mint": "Fx1JZFeYbCxLrMv7422YSxpr7YzcsAgpU1MkjZTyCKi2","owner": "8fjS2shNWY8xniiEMLNk1Aek4MAu8Qp2LCXJckVwTD4n","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "100","decimals": 2,"uiAmount": "1","uiAmountString": "1"}}],"preBalances": ["994380240", "2074080", "2074080", "1141440"],"preTokenBalances": [{"accountIndex": 1,"mint": "Fx1JZFeYbCxLrMv7422YSxpr7YzcsAgpU1MkjZTyCKi2","owner": "4fvXFPXSL9i7VbiRzoizuW4bhn1dMvRgQzQ6VevssYxw","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "100","decimals": 2,"uiAmount": "1","uiAmountString": "1"}},{"accountIndex": 2,"mint": "Fx1JZFeYbCxLrMv7422YSxpr7YzcsAgpU1MkjZTyCKi2","owner": "8fjS2shNWY8xniiEMLNk1Aek4MAu8Qp2LCXJckVwTD4n","programId": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb","uiTokenAmount": {"amount": "0","decimals": 2,"uiAmount": null,"uiAmountString": "0"}}],// --snip--}
Ανάληψη
Η διεύθυνση ανάληψης που παρέχει ο χρήστης πρέπει να είναι αυτή του SOL wallet του.
Πριν από την εκτέλεση μιας μεταφοράς ανάληψης, το ανταλλακτήριο θα πρέπει να ελέγξει τη διεύθυνση όπως περιγράφεται παραπάνω. Επιπλέον, αυτή η διεύθυνση πρέπει να ανήκει στο System Program και να μην έχει δεδομένα λογαριασμού. Εάν η διεύθυνση δεν έχει υπόλοιπο SOL, θα πρέπει να ζητηθεί επιβεβαίωση από τον χρήστη πριν από τη συνέχιση της ανάληψης. Όλες οι άλλες διευθύνσεις ανάληψης πρέπει να απορρίπτονται.
Από τη διεύθυνση ανάληψης, προκύπτει το Associated Token Account (ATA) για το σωστό mint και η μεταφορά εκδίδεται σε αυτόν τον λογαριασμό μέσω εντολής TransferChecked. Σημειώστε ότι είναι πιθανό η διεύθυνση ATA να μην υπάρχει ακόμα, οπότε το ανταλλακτήριο θα πρέπει να χρηματοδοτήσει τον λογαριασμό εκ μέρους του χρήστη. Για λογαριασμούς SPL Token, η χρηματοδότηση του λογαριασμού ανάληψης θα απαιτήσει 0.00203928 SOL (2.039.280 lamports).
Πρότυπο εντολής spl-token transfer για ανάληψη:
spl-token transfer --fund-recipient <exchange token account> <withdrawal amount> <withdrawal address>
Άλλες Εκτιμήσεις
Freeze Authority
Για λόγους κανονιστικής συμμόρφωσης, μια οντότητα έκδοσης SPL Token μπορεί προαιρετικά να επιλέξει να κατέχει "Freeze Authority" σε όλους τους λογαριασμούς που δημιουργούνται σε συσχέτιση με to mint της. Αυτό τους επιτρέπει να παγώσουν τα περιουσιακά στοιχεία σε έναν δεδομένο λογαριασμό κατά βούληση, καθιστώντας τον λογαριασμό μη χρησιμοποιήσιμο μέχρι να ξεπαγώσει. Εάν αυτή η λειτουργία είναι σε χρήση, το pubkey της αρχής παγώματος θα καταχωρηθεί στον λογαριασμό mint του SPL Token.
Βασική Υποστήριξη για το Πρότυπο SPL Token-2022 (Token Extensions)
Το SPL Token-2022 είναι το νεότερο πρότυπο για δημιουργία και ανταλλαγή wrapped/synthetic token στο blockchain της Solana.
Γνωστό επίσης ως "Token Extensions", το πρότυπο περιέχει πολλές νέες λειτουργίες που οι δημιουργοί token και οι κάτοχοι λογαριασμών μπορούν προαιρετικά να ενεργοποιήσουν. Αυτές οι λειτουργίες περιλαμβάνουν εμπιστευτικές μεταφορές, χρεώσεις μεταφοράς, κλείσιμο mints, μεταδεδομένα, μόνιμους αντιπροσώπους, αμετάβλητη κυριότητα και πολλά άλλα. Παρακαλώ δείτε τον οδηγό επεκτάσεων για περισσότερες πληροφορίες.
Εάν το ανταλλακτήριό σας υποστηρίζει SPL Token, δεν απαιτείται πολλή επιπλέον εργασία για να υποστηριχθεί το SPL Token-2022:
- το εργαλείο CLI λειτουργεί απρόσκοπτα και με τα δύο προγράμματα από την έκδοση 3.0.0 και μετά.
- Τα
preTokenBalancesκαιpostTokenBalancesπεριλαμβάνουν υπόλοιπα SPL Token-2022 - Το RPC ευρετηριάζει λογαριασμούς SPL Token-2022, αλλά πρέπει να γίνουν ερωτήματα ξεχωριστά με
program id
TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
Το Associated Token Account λειτουργεί με τον ίδιο τρόπο και υπολογίζει σωστά το απαιτούμενο ποσό κατάθεσης σε SOL για τον νέο λογαριασμό.
Λόγω των επεκτάσεων, ωστόσο, οι λογαριασμοί μπορεί να είναι μεγαλύτεροι από 165 bytes, επομένως μπορεί να απαιτούν περισσότερα από 0.00203928 SOL για χρηματοδότηση.
Για παράδειγμα, το πρόγραμμα Associated Token Account περιλαμβάνει πάντα την επέκταση "immutable owner", οπότε οι λογαριασμοί καταλαμβάνουν ελάχιστα 170 bytes, που απαιτεί 0.00207408 SOL.
Εκτιμήσεις Ανά Επέκταση
Η προηγούμενη ενότητα περιγράφει την πιο βασική υποστήριξη για το SPL Token-2022. Καθώς οι επεκτάσεις τροποποιούν τη συμπεριφορά των token, τα ανταλλακτήρια ενδέχεται να χρειαστεί να αλλάξουν τον τρόπο χειρισμού των token.
Είναι δυνατό να δείτε όλες τις επεκτάσεις σε ένα mint ή token account:
spl-token display <account address>
Χρέωση Μεταφοράς
Ένα token μπορεί να διαμορφωθεί με χρέωση μεταφοράς, όπου ένα μέρος των μεταφερόμενων tokens παρακρατείται στον προορισμό για μελλοντική συλλογή.
Εάν το ανταλλακτήριό σας μεταφέρει αυτά τα tokens, να γνωρίζετε ότι ενδέχεται να μην φτάσουν όλα στον προορισμό λόγω του παρακρατούμενου ποσού.
Είναι δυνατό να καθορίσετε την αναμενόμενη χρέωση κατά τη διάρκεια μιας μεταφοράς για να αποφύγετε τυχόν εκπλήξεις:
spl-token transfer --expected-fee <fee amount> --fund-recipient <exchange token account> <withdrawal amount> <withdrawal address>
Mint Close Authority
Με αυτή την επέκταση, ένας δημιουργός token μπορεί να κλείσει ένα mint, εφόσον η προσφορά tokens είναι μηδέν.
Όταν κλείσει ένα mint, ενδέχεται να υπάρχουν ακόμα άδειοι token accounts και δεν θα συσχετίζονται πλέον με ένα έγκυρο mint.
Είναι ασφαλές να κλείσετε απλώς αυτούς τους token accounts:
spl-token close --address <account address>
Εμπιστευτική Μεταφορά
Τα mints μπορούν να διαμορφωθούν για εμπιστευτικές μεταφορές, ώστε τα ποσά των token να είναι κρυπτογραφημένα, αλλά οι κάτοχοι λογαριασμών να παραμένουν δημόσιοι.
Τα ανταλλακτήρια μπορούν να διαμορφώσουν token accounts για αποστολή και λήψη εμπιστευτικών μεταφορών, για να αποκρύψουν τα ποσά των χρηστών. Δεν είναι απαραίτητο να ενεργοποιηθούν εμπιστευτικές μεταφορές στους token accounts, οπότε τα ανταλλακτήρια μπορούν να αναγκάσουν τους χρήστες να στέλνουν tokens μη εμπιστευτικά.
Για να ενεργοποιήσετε τις εμπιστευτικές μεταφορές, ο λογαριασμός πρέπει να διαμορφωθεί κατάλληλα:
spl-token configure-confidential-transfer-account --address <account address>
Και για τη μεταφορά:
spl-token transfer --confidential <exchange token account> <withdrawal amount> <withdrawal address>
Κατά τη διάρκεια μιας εμπιστευτικής μεταφοράς, τα πεδία preTokenBalance και postTokenBalance
δεν θα εμφανίζουν καμία αλλαγή. Για να πραγματοποιήσετε sweep των λογαριασμών κατάθεσης, πρέπει να αποκρυπτογραφήσετε
το νέο υπόλοιπο για ανάληψη των tokens:
spl-token apply-pending-balance --address <account address>spl-token withdraw-confidential-tokens --address <account address> <amount or ALL>
Προεπιλεγμένη Κατάσταση Λογαριασμού
Τα mints μπορούν να διαμορφωθούν με προεπιλεγμένη κατάσταση λογαριασμού, έτσι ώστε όλοι οι νέοι token accounts να είναι παγωμένοι από προεπιλογή. Αυτοί οι δημιουργοί token μπορεί να απαιτούν από τους χρήστες να ακολουθήσουν μια ξεχωριστή διαδικασία για να ξεπαγώσουν τον λογαριασμό.
Μη Μεταβιβάσιμο
Ορισμένα tokens είναι μη μεταβιβάσιμα, αλλά μπορούν ακόμα να καταστραφούν και ο λογαριασμός μπορεί να κλειστεί.
Μόνιμος Αντιπρόσωπος
Οι δημιουργοί token μπορούν να ορίσουν έναν μόνιμο αντιπρόσωπο για όλα τα tokens τους. Ο μόνιμος αντιπρόσωπος μπορεί να μεταφέρει ή να καταστρέψει tokens από οποιονδήποτε λογαριασμό, ενδεχομένως κλέβοντας κεφάλαια.
Αυτή είναι νομική απαίτηση για stablecoins σε ορισμένες δικαιοδοσίες, ή θα μπορούσε να χρησιμοποιηθεί για σχήματα επανάκτησης token.
Να γνωρίζετε ότι αυτά τα tokens ενδέχεται να μεταφερθούν εν αγνοία του ανταλλακτηρίου σας.
Transfer Hook
Τα tokens μπορούν να διαμορφωθούν με ένα επιπλέον πρόγραμμα που πρέπει να καλείται κατά τη διάρκεια μεταφορών, προκειμένου να επικυρωθεί η μεταφορά ή να εκτελεστεί οποιαδήποτε άλλη λογική.
Δεδομένου ότι το runtime της Solana απαιτεί να περνούν όλοι οι λογαριασμοί ρητά σε ένα πρόγραμμα, και τα transfer hooks απαιτούν επιπλέον λογαριασμούς, το ανταλλακτήριο πρέπει να δημιουργεί εντολές μεταφοράς διαφορετικά για αυτά τα tokens.
Το CLI και οι δημιουργοί εντολών όπως το
createTransferCheckedWithTransferHookInstruction προσθέτουν τους επιπλέον λογαριασμούς
αυτόματα, αλλά οι επιπλέον λογαριασμοί μπορούν επίσης να καθοριστούν ρητά:
spl-token transfer --transfer-hook-account <pubkey:role> --transfer-hook-account <pubkey:role> ...
Απαιτούμενο Σημείωμα στη Μεταφορά
Οι χρήστες μπορούν να διαμορφώσουν τους token accounts τους για να απαιτούν σημείωμα κατά τη μεταφορά.
Τα ανταλλακτήρια μπορεί να χρειαστεί να προσθέτουν μια εντολή σημειώματος πριν από τη μεταφορά tokens πίσω στους χρήστες, ή να απαιτούν από τους χρήστες να προσθέτουν μια εντολή σημειώματος πριν από την αποστολή προς το ανταλλακτήριο:
spl-token transfer --with-memo <memo text> <exchange token account> <withdrawal amount> <withdrawal address>
Δοκιμή της Ενσωμάτωσης
Φροντίστε να δοκιμάσετε την πλήρη ροή εργασίας σας στα devnet και testnet
clusters της Solana πριν μεταβείτε στην παραγωγή στο mainnet.
Το Devnet είναι το πιο ανοιχτό και ευέλικτο, και ιδανικό για αρχική ανάπτυξη, ενώ
το testnet προσφέρει πιο ρεαλιστική διαμόρφωση cluster. Τόσο το devnet όσο και το testnet
υποστηρίζουν faucet, εκτελέστε solana airdrop 1 για να αποκτήσετε κάποιο devnet ή testnet SOL
για ανάπτυξη και δοκιμές.
Is this page helpful?