Marlowe integré dans JavaScript

Marlowe est écrit comme un type de données Haskell, et il est donc facile de générer des contrats intelligents Marlowe en utilisant Haskell. Néanmoins, nous fournissons également une bibliothèque écrite en TypeScript qui peut être utilisée pour générer des contrats intelligents Marlowe à partir de TypeScript ou de JavaScript de la même manière qu'en utilisant Haskell. Si vous n'êtes pas familier avec TypeScript, vous pouvez également utiliser l'API comme si elle était écrite en JavaScript puisque TypeScript est un surensemble de JavaScript.

Vous pouvez essayer la bibliothèque en ligne en sélectionnant l'onglet JS Editor dans le Marlowe Playground. En haut de l'onglet, vous trouverez plusieurs exemples illustrant l'utilisation de la bibliothèque.

Utilisation de l'onglet JS Editor

La bibliothèque JavaScript/TypeScript fournit des définitions de constantes pour les constructions Marlowe qui n'ont pas d'arguments, comme c'est le cas de SlotIntervalEnd:

ou le contrat Close :

Les constructions qui ont des arguments sont représentées comme des fonctions, comme dans le cas de AvailableMoney:

Vous pouvez voir les déclarations de type pour chacune des constructions et chacun des types en passant la souris sur l'identifiant dans la déclaration d'importation au début du fichier apparaissant dans l'éditeur de l'onglet JS Editor. La déclaration d'importation et la déclaration de fonction sont grisées pour signaler qu'elles ne doivent pas être modifiées, que le code qui génère le contrat doit être écrit dans le corps de la fonction fournie et que le contrat résultant doit être renvoyé comme résultat de la fonction (à l'aide de l'instruction return ).

Intérieurement, les fonctions et les constantes de la bibliothèque JavaScript/TypeScript renvoient une représentation JSON des constructions Marlowe. Par exemple, la fonction AvailableMoney est définie comme suit :

Lorsque vous cliquez sur le bouton Compile dans l'onglet JS du Marlowe Playground, le code dans le corps de l'onglet est exécuté, et l'objet JSON renvoyé par la fonction pendant l'exécution est transformé en un contrat Marlowe réel qui peut ensuite être envoyé dans l'onglet Simulation où il peut être simulé.

L'implémentation de la bibliothèque elle-même est assez simple, vous pouvez trouver l'ensemble de son code source ici. En principe, nous pourrions écrire du code JavaScript qui produit directement la représentation JSON de Marlowe, mais vous ne devriez pas avoir à vous soucier du JSON du tout en utilisant la bibliothèque JS.

Lorsque vous utilisez la bibliothèque JS Marlowe, et que votre utilisation des fonctions et des constantes de la bibliothèque fait l'objet d'une vérification de type, le résultat de votre code doit produire une représentation JSON valide d'un contrat Marlowe. Nous assurons donc la sécurité de la génération des contrats grâce au système de types de TypeScript.

Le type  SomeNumber

Il y a un type important qui n'est pas présent dans la définition Haskell de Marlowe, nous avons appelé ce type SomeNumber, et il est défini comme suit :

La raison pour laquelle nous disposons de ce type est que le type natif des numéros en JavaScript et TypeScript perd en précision lorsqu'il est utilisé avec de grands numéros entiers. Cela est dû au fait que son implémentation repose sur des numéros à virgule flottante.

L'expression suivante est valable dans JavaScript:

Cela peut être problématique pour les contrats financiers, car cela peut entraîner une perte d'argent.

Nous recommandons donc l'utilisation du type bigint . Mais nous supportons trois façons de représenter les numéros pour des raisons de commodité et de rétrocompatibilité avec les anciennes versions de JS:

  • Numéros natifs:
    • Ils sont simples à utilizer
    • La notation est très simple et peut être utilisée avec des opérateurs standards, par exemple: 32 + 57
    • Ils perdent de la précision pour les grandes quantités
  • Représentation en chaînes de caractères:
    • Pour noter, il suffit d'ajouter des guillemets autour des chiffres
    • Vous ne pouvez pas utiliser directement les opérateurs standards, par exemple: "32" + "57" = "3257"
    • Ils ne perdent pas en précision
  • Les types bigint :
    • Ils sont simples à utiliser (il suffit d'ajouter n après les littéraux numériques)
    • La notation est très simple et peut être utilisée avec des opérateurs standards, par exemple: 32n + 57n
    • Ils ne perdent pas en précision

 

Toutes ces représentations sont converties en BigNumber internellement, mais une perte de précision peut se produire si des nombres natifs sont utilisés, car le BigNumber est construit, avant que la conversion ne se produise, et l'API ne peut rien faire à ce sujet.

Le type EValue et la surcharge des booléens

En Haskell, les observations booléennes constantes sont représentées par TrueObs et FalseObs, et les valeurs entières constantes sont représentées par Constant suivi par un Integer. En JavaScript et TypeScript, vous pouvez également utiliser ces constructeurs, mais vous n'êtes pas obligé de le faire, car le type Observation est surchargé pour accepter également les booléens natifs de JavaScript, et les fonctions qui, en Haskell, prennent une valeur de Value, en JavaScript, ils prennent une EValue à la place, et EValue est définie comme suit :

Exemple : Rédaction d'un contrat de Swap en TypeScript

Lorsque nous commençons par modifier un exemple existant ou par créer un nouveau contrat JavaScript, la liste des importations et la déclaration de fonction nous sont automatiquement fournies. Nous pouvons commencer par supprimer tout ce qui n'est pas grisé, et commencer à écrire entre les crochets de la définition de fonction fournie.

Disons que nous voulons rédiger un contrat pour qu'Alice puisse échanger 1000 Ada avec Bob contre 100 $.

Tout d'abord, calculons les quantités de chaque unité avec lesquelles nous voulons travailler. Nous pouvons définir des constantes numériques en utilisant const:

Le montant figurant dans le contrat doit être écrit en Lovelace, qui correspond à 0,000001 Ada. Nous calculons donc le montant en Lovelace en multipliant les 1 000 Ada par 1 000 000. Le montant en dollars est de 100 dans notre exemple.

L'API fournit déjà un constructeur pour la devise ADA, et il n'y a pas actuellement de symbole de devise dans Cardano pour les dollars, mais imaginons qu'il y en ait un, et définissons-le comme suit :

Le string "85bb65" correspondrait en réalité au symbole de la monnaie, qui est un hachage et doit être écrit en base16 (représentation hexadécimale d'un byte string). Et le string "dollar" correspondrait au nom du token.

Définissons maintenant un type d'objet pour contenir les informations sur les parties et ce qu'elles veulent échanger, pour des raisons de commodité:

Nous enregistrerons le nom de la partie dans le champ party, le nom de la devise dans le champ currency, et le montant de la devise que la partie veut échanger dans le champ amount:

Nous sommes maintenant prêts à commencer à rédiger notre contrat. Tout d'abord, définissons les dépôts. Nous prenons les informations de la partie qui doit effectuer le dépôt, le numéro du slot jusqu'auquel nous attendrons que le dépôt soit effectué, et le contrat de continuation qui sera appliqué si le dépôt est réussi.

Nous avons seulement besoin d'une construction When avec un seul Case qui représente un Deposit de la partie src sur son propre compte, de cette façon, si nous annulons le contrat avant l'échange, chaque partie récupérera ce qu'elle a déposé.

Ensuite, nous définissons l'un des deux paiements de l'échange. Nous prenons les parties source et destination comme paramètres, ainsi que le contrat de continuation qui sera appliqué après le paiement.

Pour cela, il suffit d'utiliser la construction Pay pour payer depuis le compte sur lequel la partie source a effectué le dépôt vers la partie destinataire.

Enfin, nous pouvons combiner tous les morceaux:

Le contrat comporte quatre étapes:

  1. Alice peut déposer jusqu'àu slot 10
  2. Bob peut déposer jusqu'au slot 20 (sinon Alice est remboursée et le contrat est annulé)
  3. Ensuite, nous payons le dépôt d'Alice à Bob
  4. Nous payons le dépôt de Bob à Alice.

 

Et c'est tout. Vous trouverez le code source complet du contrat intelligent swap dans les exemples du Marlowe Playground, que nous examinerons ensuite.

© Copyright 2020, IOHK Revision 34c4781c.

 

Vous trouverez une copie officielle de ce document ici :

https://alpha.marlowe.iohkdev.io/doc/marlowe/tutorials/javascript-embedding.html

https://docs.cardano.org/projects/plutus/en/latest/marlowe/tutorials/javascript-embedding.html

 

Plus de traductions de Cardano à: Cardano For The World