Auteur : @Web3Mario (https://x.com/web3_mario)
Résumé : Suite à l'article précédent sur TON Article d'introduction technique , j'ai étudié en profondeur les documents de développement officiels de TON pendant cette période, et j'ai l'impression qu'il existe encore des obstacles à l'apprentissage. Le contenu du document actuel semble ressembler davantage à un document de développement interne, ce qui n'est pas très. convivial pour les nouveaux développeurs. Par conséquent, j'essaie de trier une série d'articles sur le développement de projets TON Chain en fonction de ma propre trajectoire d'apprentissage. J'espère qu'il sera utile pour tout le monde de démarrer rapidement avec TON DApp. développement. S'il y a des erreurs dans l'écriture, vous pouvez me corriger et apprendre ensemble.
Quelles sont les différences entreIssuing un FT ou NFT C'est généralement le besoin le plus élémentaire des développeurs DApp. Je l'utilise donc également comme point d'entrée pour l'apprentissage. Tout d'abord, comprenons les différences suivantes entre le développement d'un NFT dans la pile technologique EVM et dans TON Chain.NFT basé sur EVM choisit généralement d'hériter de la norme ERC-721. Ce qu'on appelle NFT fait référence à un type indivisible d'actif cryptographique, et chaque actif est unique, c'est-à-dire qu'il possède certaines caractéristiques exclusives. Et ERC-721 est un paradigme de développement commun pour ce type d'actifs. Jetons un coup d'œil aux fonctions qu'un contrat ERC721 commun doit mettre en œuvre et quelles informations sont enregistrées. L'image ci-dessous est une interface ERC721. Vous pouvez constater que contrairement à FT, ce qu'il faut saisir dans l'interface de transfert, c'est le tokenId à transférer à la place de la quantité.Ce tokenId est également l'incarnation la plus basique du caractère unique de NFT. Bien sûr, afin de comporter plus d'attributs, une métadonnées est généralement enregistrée pour chaque tokenId, ceci. Les métadonnées sont un lien externe qui enregistre d'autres données évolutives du NFT, comme un lien vers une image PFP, certains noms d'attributs, etc.
Pour les développeurs familiers avec Solidity ou familiers avec l'orientation objet, il est facile de mettre en œuvre un tel contrat intelligent, à condition que les types de données requis dans le contrat soient définis, tels que quelques mappages clés Relation mapping, et développer la logique de modification correspondante à ces données en fonction des fonctions requises, vous pouvez implémenter un NFT.
Cependant, dans TON Chain, tout est différent. Il y a deux raisons principales à la différence :
.TON et EVM.Dans la discussion initiale, nous savons qu'un contrat NFT doit définir certaines relations de cartographie, c'est-à-dire mapping, pour enregistrer les données associées NFT. Le plus important est owners. Ce mapping stocke la relation de mappage de l'adresse du propriétaire d'un certain tokenID correspondant à NFT, qui détermine la propriété et le transfert de NFT. Il s'agit d'une modification de cette propriété. Puisqu’il s’agit d’une structure de données qui peut être illimitée en théorie, elle doit être évitée autant que possible. Par conséquent, il est officiellement recommandé d’utiliser l’existence de structures de données illimitées comme norme de partitionnement. Autrement dit, lorsqu'il existe des exigences de stockage de données similaires, le paradigme de contrat maître-esclave est utilisé à la place, et les données correspondant à chaque clé sont gérées en créant des sous-contrats. Et gérez les paramètres globaux via le contrat principal, ou aidez à gérer l'interaction des informations internes entre les sous-contrats.
Cela signifie également que le NFT de TON doit également être conçu avec une architecture similaire. Chaque NFT est un sous-contrat indépendant, enregistrant des éléments tels que l'adresse du propriétaire, . métadonnées et autres données exclusives, et un contrat principal est utilisé pour gérer les données globales, telles que Nom NFT, symbole, approvisionnement total, etc.
Après avoir clarifié l'architecture, l'étape suivante consiste à résoudre les exigences fonctionnelles de base. En raison de l'adoption de cette méthode de contrat maître-esclave, Il est donc nécessaire de clarifier quelles fonctions sont portées par le contrat principal et lesquelles. les fonctions sont portées par le sous-traitant. Et quelles informations internes sont communiquées entre les deux, et comment restaurer les données précédentes lorsqu'une erreur d'exécution se produit. Habituellement, avant de développer un projet complexe à grande échelle, il est nécessaire de passer un diagramme de classes et de clarifier le flux d'informations entre eux, et de réfléchir attentivement à la logique de restauration après un échec d'appel interne. Bien sûr, ce qui précède NFT. le développement est simple, mais une vérification similaire peut également être effectuée.
TONChoisissez de concevoir une classe C langage de type statique, nommé Func en tant que contrat intelligent langage de développement, apprenons ensuite à développer des contrats intelligents TON à partir du code source. J'ai choisi l'exemple NFT dans le document officiel de TON pour le présenter. Les amis intéressés peuvent le consulter. vous-même. Un exemple simple de TON NFT est implémenté dans ce cas. Jetons un coup d'œil à la structure du contrat, qui est divisée en deux contrats fonctionnels et trois bibliothèques nécessaires.
Ces deux contrats fonctionnels principaux sont conçus selon les principes ci-dessus. Tout d'abord, regardons le code du contrat principal nft-collection :
.Cela introduit le premier point de connaissance, comment stocker de manière persistante des données dans TON contrats intelligents Nous savons que le stockage persistant des données dans Solidity est effectué par EVM selon les paramètres Le type. est automatiquement géré, les variables d'état du contrat intelligent seront automatiquement conservées et stockées en fonction de la dernière valeur après l'exécution. Mais ce n'est pas le cas dans Func Les développeurs doivent implémenter eux-mêmes la logique de traitement correspondante. Cette situation est quelque peu similaire au processus de C et C++ qui doivent prendre en compte GC. . Mais d'autres nouveaux langages de développement automatisent généralement cette partie de la logique. Jetons un coup d'œil au code. Tout d'abord, nous introduisons quelques bibliothèques requises, puis nous voyons que la première fonction load_data est utilisée pour lire les données stockées de manière persistante. Sa logique est de renvoyer d'abord les données persistantes via . get_data Stockage sous contrat cell Notez que ceci est implémenté par la bibliothèque standard stdlib.fc Dans des circonstances normales, certaines de ces fonctions peuvent être utilisées comme fonctions système.
Le type de valeur de retour de cette fonction est cell, qui est le type cell dans TVM. Dans l'introduction précédente, nous savons déjà que toutes les données persistantes de la blockchain TON sont stockées dans l'arborescence cell. Chaque cell contient au plus 1023 bits de données arbitraires et jusqu'à quatre références à d'autres cell. cell est utilisée comme mémoire dans TVM basé sur une pile.cell stocke des données étroitement codées. Pour obtenir les données spécifiques en texte brut, vous devez convertir cell en un type appelé slice. cell peut être converti en type slice par la fonction begin_parse, qui peut ensuite être obtenu en chargeant des bits de données et des références à d'autres cell à partir de slice Données dans . Notez que cette méthode d'appel dans la ligne de code 15 est un sucre syntaxique dans func, qui peut appeler directement la deuxième fonction avec la valeur de retour de la première fonction. Et enfin chargez les données correspondantes dans l'ordre selon l'ordre de persistance des données.Notez que ce processus est différent de solidity et n'est pas appelé en fonction de hashmap, donc l'ordre des appels ne peut pas être gâché.
Dans la fonction save_data, la logique est similaire, sauf qu'il s'agit d'un processus inverse, qui introduit le point de connaissance suivant, un nouveau type builder, c'est Le type de cellule constructeur. Les bits de données et les références à d'autres cell peuvent être stockées dans des constructeurs, qui peuvent ensuite être finalisées dans une nouvelle cell. Créez d'abord un builder via la fonction standard begin_cell, et stockez les fonctions associées via les fonctions associées store Notez que l'ordre d'appel ci-dessus doit être cohérent avec l'ordre de stockage ici.Enfin, la nouvelle cell est construite via end_cell À ce moment, la cell est gérée dans la mémoire. Enfin, via le set_data le plus externe. stockage persistant de cell.
Ensuite, jetons un coup d'œil aux fonctions liées à l'entreprise. Tout d'abord, nous devons introduire le point de connaissance suivant, comment créer un nouveau contrat via un contrat, qui sera fréquemment utilisé dans l'architecture maître-esclave qui vient d'être introduite. Nous savons que dans TON, les appels entre contrats intelligents sont mis en œuvre par l'envoi de messages internes. Ceci est réalisé grâce à un fichier appelé send_raw_message. Notez que le premier paramètre est le messagecodé cell, et le deuxième paramètre est le bit d'identification, utilisé pour indiquer la transaction. méthodes d'exécution, différentes méthodes d'exécution d'envoi de messages internes sont définies dans TON, a actuellement 3 types de messagesModes et 3types de messagesFlags. Un seul Mode peut être combiné avec plusieurs drapeaux (peut-être aucun) pour obtenir le mode souhaité.La combinaison signifie simplement remplir la somme de leurs valeurs. Le tableau de description des Modes et Flags est donné ci-dessous :
Regardons donc la première fonction principale, deploy_nft_item, comme son nom l'indique, c'est une fonction pour La fonction qui crée ou lance une nouvelle instance NFT Après quelques opérations pour encoder un msg, le contrat interne est envoyé via send_raw_message, et l'envoi de flag 1. est sélectionné. Bit d'identification, seuls les frais spécifiés dans l'encodage sont utilisés comme frais d'essence pour cette exécution. Après l’introduction ci-dessus, on peut facilement se rendre compte que cette règle de codage doit correspondre à la manière de créer un nouveau contrat intelligent. Voyons ensuite comment cela est mis en œuvre.
Regardons directement la ligne 51 Les deux fonctions ci-dessus sont des fonctions auxiliaires utilisées pour générer les informations requises pour message, nous y reviendrons donc plus tard. créer un contrat intelligent Dans le processus d'encodage, certains chiffres au milieu sont en fait des bits d'identification, utilisés pour expliquer les besoins du message interne. Le point de connaissance suivant est introduit ici TON a choisi un type appelé TL. -B Le langage binaire est utilisé pour décrire la façon dont les messages sont exécutés et les messages internes qui implémentent certaines fonctions spécifiques basées sur la définition de différents bits d'indicateur. Les deux scénarios d'utilisation les plus faciles à imaginer sont la création de nouveaux contrats et les appels de fonctions de contrat déployés. La méthode de la ligne 51 correspond à la première, créant un nouveau contrat nft item, qui se fait principalement via 55, 56, 57 Trois lignes sont spécifié.Tout d'abord, la grande série de nombres dans la ligne 55 est une série de bits d'identification. Notez que le premier paramètre d'entrée de store_uint est une valeur numérique, et le second est une longueur en bits, qui détermine si le message interne est créé par le contrat. sont les trois derniers bits de marque, et les bits de valeur binaire correspondants sont 111 (l'équivalent décimal est 4+2+1), où le premier. deux indiquent que le message sera accompagné de données StateInit, ces données sont le code source du nouveau contrat et les données nécessaires à l'initialisation. Ce dernier bit indicateur indique la pièce jointe du message interne, c'est-à-dire que la logique pertinente et les paramètres requis devraient être exécutés. Par conséquent, vous verrez que les données à trois chiffres ne sont pas définies dans la ligne 66, ce qui indique un appel de fonction au contrat déployé. Les règles de codage détaillées peuvent être trouvées ici.
Ensuite, les règles d'encodage de StateInit correspondent à 49 lignes de code, calculées via calculate_nft_item_state_init Notez que l'encodage de stateinitdata également. suit un établi TL- BLes règles d'encodage, à l'exception de certains bits de drapeau, impliquent principalement deux parties du nouveau contrat code et initialisation données. L'ordre d'encodage des data doit être cohérent avec l'ordre de stockage des cell persistantes spécifié par le nouveau contrat.Comme vous pouvez le voir dans la ligne 36, les données d'initialisation incluent item_index, qui est similaire à tokenId dans ERC721, et la fonction standard mon _ adresse L'adresse actuelle du contrat renvoyée est collection_address L'ordre de ces données est cohérent avec la déclaration dans nft-item.
Le prochain point de connaissance est que dans TON, tous les contrats intelligents non générés peuvent pré-calculer leurs adresses générées. Ceci est similaire à la fonction create2 dans La génération d'un nouveau. L'adresse dans TON se compose de deux parties, le bit d'identification workchain et la valeur de hachage de stateinit. Nous savons déjà que la première est destinée au TON correspondant. spécifiée pour l’architecture de partitionnement infini est actuellement une valeur unifiée. Obtenu à partir de la fonction standard workchain. Cette dernière est obtenue par la fonction standard cell_hash. Revenons donc à cet exemple, calculate_nft_item_address est une fonction qui pré-calcule la nouvelle adresse du contrat. Et encodez la valeur générée dans la ligne 53 dans message comme adresse de réception du message interne.Et nft_content correspond à l'appel d'initialisation du contrat créé. L'implémentation spécifique sera présentée dans le prochain article.
Quant à send_royalty_params, il doit être une réponse au message interne d'une requête en lecture seule. Dans l'introduction précédente, nous avons spécifiquement souligné que le message interne dans TON n'est pas seulement. contient des modifications possibles Les opérations de données et les opérations en lecture seule doivent également être implémentées de cette manière, ce contrat est donc une telle opération. La première chose à noter est que la ligne 67 indique la marque de la fonction de rappel du demandeur après. en réponse à la demande. Notez-la. Ce sont les données renvoyées, qui sont les index d'article demandés et les données de royauté correspondantes.
Présentons le prochain point de connaissance. Il n'y a que deux entrées unifiées aux contrats intelligents dans TON, nommées recv_internal et recv_external, où la première est l'unification de tous les messages internes. Entrée d'appel, cette dernière est une entrée d'appel unifiée pour tous les messages externes. Les développeurs doivent utiliser une méthode similaire à switch dans la fonction pour répondre à différentes demandes en fonction des différents bits d'indicateur spécifiés par message. Ici, le bit de marque est la marque de fonction de rappel de la ligne ci-dessus 67. Revenons à cet exemple, effectuez d'abord une vérification des postes vacants sur message, puis analysez les informations dans message respectivement. Tout d'abord, analysez la ligne 83 pour obtenir sender_address. . Les paramètres seront utilisés pour les vérifications d'autorisation ultérieures. Notez que les opérateurs ~ ici sont un autre sucre syntaxique. Je ne m’étendrai pas là-dessus ici.Ensuite, les bits d'indicateur de l'opération op sont analysés, puis les requêtes correspondantes sont traitées en fonction de différents bits d'indicateur. Parmi elles, les fonctions ci-dessus sont appelées respectivement selon une certaine logique. Par exemple, répondez à une demande pour le paramètre royalty, ou créez un nouveau nft et incrémentez l'index global.
Le point de connaissance suivant correspond à la ligne 108 Je pense que vous pouvez également connaître la logique de traitement de cette fonction en la nommant. Elle est similaire à la fonction require dans Solidity, . Func Les exceptions sont levées via la fonction standard throw_unless Le premier paramètre d'entrée est le code d'erreur, et le second consiste à vérifier la valeur booléenne du bit. Si le bit est false, une exception. sera lancé avec le code d'erreur. Dans cette ligne, equal_slices est utilisé pour déterminer si le sender_address analysé ci-dessus est égal au owner_address du stockage persistant du contrat, et rendre un jugement d'autorisation.
Enfin, afin de rendre la structure du code plus claire, une série de fonctions auxiliaires ont été développées pour aider à obtenir des informations de persistance. Elles ne seront pas présentées ici. Les développeurs peuvent se référer à cette structure pour développer leur propre smart. contrats.
Le développementTONécologique DApp est vraiment une chose intéressante, et il est très différent du paradigme de développement de EVM, je vais donc vous présenter comment développer dans TON Chain à travers une série d'articles Développé dans DApp. Apprenez ensemble avec tout le monde et saisissez cette vague d’opportunités. Vous êtes également invités à interagir avec moi sur twitter pour découvrir de nouvelles et intéressantes idées dapp et les développer ensemble.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!