Tutoriel de développement IBAX
Guide de démarrage
- Déployer le premier contrat intelligent via l'outil en ligne de commande
- Développement de l'écosystème de l'outil en ligne de commande
Déploiement
- Déployer une application à l'aide des outils en ligne de commande
- Configuration écologique à l'aide de l'outil en ligne de commande
Guide Avancé
Déployer le premier smart contract via l'outil en ligne de commande
Nous allons déployer des smart contracts sur la blockchain IBAX via l'outil en ligne de commande et apprendre comment invoquer des smart contracts. En tant que premier smart contract, nous l'avons déployé sur le réseau de test local. Pour savoir comment déployer un réseau local, vous pouvez vous référer à Déploiement du réseau, ainsi vous pouvez le déployer et l'exécuter comme vous le souhaitez sans aucun surcoût.
Créer une application
Appelez le contrat @1NewApplication pour créer l'application, qui a un paramètre de nom d'application et un paramètre de permission de modification.
1 $ ibax-cli console
2
3 Bienvenue dans la console IBAX !
4 Pour quitter, appuyez sur ctrl-d ou tapez exit
5 >callContract @1NewApplication {"Name": "testapp", "Conditions": "ContractConditions(\"@1DeveloperCondition\")"}
6
7 {
8 "block_id": 1217,
9 "hash": "6327161d2202c33c06d34ab4ed9b509c05fc2cbb15cf260c6d3d404a6f640028",
10 "penalty": 0,
11 "err": "31"
12 }
Les éléments suivants sont expliqués par ligne :
- Ligne 1, démarrer le terminal de ligne de commande
- Ligne 5, appeler le contrat @1NewApplication pour créer une application avec
le nom d'application
testapp
et la permission de modification de l'application@1DeveloperCondition
avec la permission du développeur - Ligne 8, l'identifiant de bloc généré par la transaction
- Ligne 9, le hachage de bloc généré par la transaction
- Ligne 10, si l'exécution de la transaction échoue (0 : pas de pénalité, 1 : pénalité)
- Ligne 11, si l'exécution de la transaction échoue, un message d'erreur est renvoyé, et si l'identifiant de bloc est renvoyé, le champ err est l'identifiant de l'application
Bien sûr, si vous souhaitez voir quels champs et types de champs sont
disponibles dans ce contrat, vous pouvez appeler la méthode getContractInfo
,
qui renverra les informations sur le contrat comme suit:
>getContractInfo @1NewApplication
{
"id": 5022,
"state": 1,
"tableid": "22",
"walletid": "0",
"tokenid": "1",
"address": "0000-0000-0000-0000-0000",
"fields": [
{
"name": "Name",
"type": "string",
"optional": false
},
{
"name": "Conditions",
"type": "string",
"optional": false
},
{
"name": "VotingId",
"type": "int",
"optional": true
}
],
"name": "@1NewApplication",
"app_id": 1,
"ecosystem": 1,
"conditions": "ContractConditions(\"@1DeveloperCondition\")"
}
Le champ fields
est constitué des paramètres du contrat, incluant le nom du
paramètre name
, type
, optional
, Name
et Conditions
sont requis,
VotingId
est optionnel, consultez la méthode API
contract/name
Rédaction de contrats
Nous utilisons Needle pour
écrire un contrat intelligent. Nous implémentons une opération d'addition
simple, le code source du contrat est le suivant, nous enregistrons le contrat
sous le nom SumMath.sim
.
1 contract SumMath {
2 data {
3 A int
4 B int
5 }
6 conditions {
7
8 }
9 action {
10 var sum int
11 sum = $A + $B
12 $result = sum
13 }
14 }
Le suivant est expliqué par ligne :
- À la ligne 1, nous définissons un contrat avec le nom SumMath.
- Ligne 2, Section des données.
- Aux lignes 3-4, nous définissons deux paramètres de type entier 64 bits en
entrée,
A
etB
. - Ligne 6, Section conditionnelle.
- Ligne 9, Section des opérations. Nous
définissons une variable
sum
pour recevoir le résultat de A+B. Nous assignons la valeur desum
à$result
, en tant que résultat du contrat. Bien sûr, il est possible d'assigner directement la valeur de A+B à$result
, mais cela peut être montré comme un exemple.
Créer un contrat
Il existe deux façons de créer un contrat, dont la première est la suivante : Dans la première étape, nous rédigeons un fichier de paramètres de contrat au format json :
{
"ApplicationId": 31,
"Value": "contract SumMath {\n data {\n A int\n B int\n }\n conditions {\n\n }\n action {\n var sum int\n sum = $A + $B\n $result = sum\n }\n}",
"Conditions": "ContractConditions(\"@1DeveloperCondition\")"
}
où ApplicationId
est l'identifiant de l'application, Value
est le code
source du contrat, il est nécessaire d'échapper les caractères spéciaux,
Conditions
sont les droits de modification du contrat.
Nous l'avons nommé SumMathParams.json.
La deuxième étape consiste à appeler la création d'un contrat @1NewContract:
1 >callContract @1NewContract -f=./data/SumMathParams.json
2 {
3 "block_id": 1238,
4 "hash": "f3fe7aff8a613c96299723b7e9af0682aa8cabe7becf67a485e2a77a974f58b6",
5 "penalty": 0,
6 "err": "328"
7 }
Deuxième méthode : Le fichier source du contrat enregistré est directement
transmis aux paramètres du contrat dans le format de paramètre nomParamètre
+
-
+ "fichier", nomParamètre-fichier
comme suit :
1 >callContract @1NewContract {"ApplicationId": 31, "Value-file": "SumMath.sim", "Conditions": "true"}
2 {
3 "block_id": 2055,
4 "hash": "cdf25060669cf7cba137278...26ca463fd5d458f3402a5f0137f693db",
5 "penalty": 0,
6 "err": "368"
7 }
Le suivant est expliqué par ligne :
- Ligne 1 : Appeler le contrat @1NewContract pour créer le contrat, -f utilise le fichier pour importer les paramètres du contrat
- Ligne 3 : L'identifiant de bloc généré par la transaction
- Ligne 4 : Le hachage de bloc généré par la transaction
- Ligne 5 : Si l'exécution de la transaction échoue (0 : pas de pénalité, 1 : pénalité)
- Ligne 6 : Si l'exécution de la transaction échoue, un message d'erreur est renvoyé, et si l'identifiant de bloc est renvoyé, le champ err est l'identifiant du contrat
Essayons d'appeler le contrat que nous venons de déployer.
1 >callContract @5SumMath {"A":1, "B":2}
2
3 {
4 "block_id": 1239,
5 "hash": "7fa09da0b9f65634119a910f9d91aaf4927208278efd62961499ef7e4f4c8c9c",
6 "penalty": 0,
7 "err": "3"
8 }
L'appel est terminé et le résultat est conforme aux attentes, comme expliqué ci-dessous par ligne :
- La première ligne appelle le contrat, ici nous déployons le contrat dans
l'écosystème avec l'identifiant écologique 5. Bien sûr, si l'identifiant
écologique actuel est 5, dans le même écosystème, vous pouvez également
appeler
callContract SumMath {"A":1, "B":2}
de cette manière. - Ligne 3, l'identifiant de bloc généré par la transaction.
- Ligne 4, le hachage de bloc généré par la transaction.
- Ligne 5, si l'exécution de la transaction échoue (0 : pas de pénalité, 1 : pénalité).
- Ligne 6, si l'exécution de la transaction échoue, un message d'erreur est
renvoyé, et si l'identifiant de bloc est renvoyé, le champ err est le résultat
du contrat, qui est la valeur de
$result
.
Outil en ligne de commande pour le développement écologique
Dans ce tutoriel, vous apprendrez comment :
Afin de comprendre plus clairement à quoi ressemble l'écosystème et les applications IBAX et ce qu'ils font, il est préférable de comprendre où l'écosystème et les applications devraient appartenir, et nous pouvons mieux comprendre avec une carte mentale simple :
Il est possible de constater que les réseaux IBAX peuvent avoir de nombreux Écosystèmes. Chaque écosystème peut avoir plusieurs applications. Chaque application possède un contrat. Tables. Chaque écosystème possède des paramètres écologiques, chaque application possède des paramètres d'application.
Étape 1 : Créer un écosystème
Nous commençons par créer un écosystème en utilisant l'outil en ligne de commande (https://github.com/IBAX-io/ibax-cli), en appelant le contrat @1NewEcosystem. Si vous souhaitez changer le nom de l'écosystème, vous pouvez appeler le contrat @1EditEcosystemName.
1 $ ibax-cli console
3 Welcome to the IBAX console!
4 To exit, press ctrl-d or type exit
5 >callContract @1NewEcosystem {"Name": "goodBoy school"}
6
7 {
8 "block_id": 1199,
9 "hash": "a1dc90c1772545c16394b9521...227676b27b145743556a8973dd",
10 "penalty": 0,
11 "err": "18"
12 }
Les éléments suivants sont expliqués par ligne :
- Ligne 1, qui lance le programme de console de ligne de commande
- Ligne 5, appelle le contrat
@1NewEcosystem
pour créer un écosystème avec le nom "test ecosystem" - Ligne 8, l'identifiant de bloc généré par la transaction
- Ligne 9, le hachage de bloc généré par la transaction
- Ligne 10, si l'exécution de la transaction échoue (0 : pas de pénalité, 1 : pénalité)
- Ligne 11, si l'exécution de la transaction échoue, un message d'erreur est
renvoyé, et si l'identifiant de bloc est renvoyé, le champ d'erreur est
l'identifiant de l'écosystème en tant que
18
Ensuite, nous configurons l'outil de commande config.yml
, nous définissons
ecosystem
sur l'ecid créé 18
et redémarrons le programme de console de ligne
de commande:
>exit
INFO[0002] Exit
$ vim data/config.yml
$ ibax-cli console
Welcome to the IBAX console!
To exit, press ctrl-d or type exit
>
Étape 2 : Créer une application
Appeler le contrat @1NewApplication
pour créer l'application, qui a un
paramètre de nom d'application et un paramètre de modification
Paramètre de Permission
1 >callContract @1NewApplication {"Name": "GradesRecorder", "Conditions": "ContractConditions(\"@1DeveloperCondition\")"}
2
3 {
4 "block_id": 1246,
5 "hash": "85ab8953d26d0d1047fc610866115331babfaf88c80792d50b41826185c9f6f8",
6 "penalty": 0,
7 "err": "47"
8 }
Si vous devez modifier les autorisations de l'application, vous pouvez appeler
le contrat EditApplication
.
Ce qui suit est expliqué par ligne :
- Ligne 1, appelez le contrat @1NewApplication pour créer une application, le
nom de l'application est
GradesRecorder
, la permission de modification de l'application est la permission du développeur@1DeveloperCondition
. - Ligne 4, l'ID de bloc généré par la transaction.
- Ligne 5, le hachage de bloc généré par la transaction.
- Ligne 6, si l'exécution de la transaction échoue (0 : pas de pénalité, 1 : pénalité).
- Ligne 7, si l'exécution de la transaction échoue, un message d'erreur est
renvoyé, et si l'ID de bloc est renvoyé, le champ err contient l'ID de
l'application qui est
47
.
Écrivons un exemple simple d'une application qui suit les notes des étudiants.
Les champs de la table de données comprennent les informations sur l'étudiant,
la note grade
, la classe class
, les notes de matières
mathématiques, physique, littérature
, le score global overall_score
, la note
score
, le timestamp de création (ms) created_at
.
Étape 3 : Créer une table
Dans la première étape, nous rédigeons un fichier de paramètres de contrat au format json :
{
"ApplicationId": 47,
"Name": "grade_info",
"ColumnsArr": [
"student",
"grade",
"class",
"mathematics",
"physics",
"literature",
"overall_score",
"score",
"created_at"
],
"TypesArr": [
"varchar",
"number",
"number",
"number",
"number",
"number",
"number",
"varchar",
"number"
],
"InsertPerm": "ContractConditions(\"MainCondition\")",
"UpdatePerm": "ContractConditions(\"MainCondition\")",
"ReadPerm": "true",
"NewColumnPerm": "ContractConditions(\"MainCondition\")"
}
où ApplicationId
est l'identifiant de l'application, Name
est le nom de la
table de données créée test_table
. ColumnsArr
est un tableau de champs de la
table de données, TypesArr
est le type des champs de la table de données,
comprenant 9 types varchar
,
character
, json
, number
, datetime
, double
, money
, text
, bytea
,
le nom du champ et le type de champ sont en correspondance un à un. InsertPerm
pour la permission de nouvelle entrée dans la table de données, UpdatePerm
pour la permission de mise à jour des entrées de la table de données, ReadPerm
pour la permission de lecture des données de la table de données,
NewColumnPerm
pour la permission de nouveau champ de la table de données.
En référence au
Contrôle des autorisations,
ici ContractConditions(\"MainCondition\")
est disponible pour le créateur de
l'écosystème actuel.
Nous l'appelons createTable.json, puis nous appelons le contrat pour créer la
table de données @1NewTableJoint
.
>callContract @1NewTableJoint -f ./createTestTable.json
Modifier les autorisations des champs de la table de données
Nous pouvons modifier les autorisations des champs de la table de données. Les
autorisations des champs de la table de données comprennent les autorisations de
lecture et de mise à jour. Les autorisations de lecture permettent d'utiliser le
filtre DBFind.Columns
dans le contrat ou des interfaces telles que
list pour effectuer des
requêtes. Si aucune autorisation n'est accordée, une erreur de permission sera
signalée. La permission de mise à jour est la permission de modifier les champs
de la table de données. Nous avons défini les autorisations de lecture et de
mise à jour du champ "student" sur "false", mais bien sûr, elles peuvent être
rendues opérationnelles par certains contrats. Appelez le contrat @1EditColumn
pour modifier les autorisations des champs de la table de données.
>callContract @1EditColumn {"TableName": "grade_info", "Name": "student", "UpdatePerm": "false", "ReadPerm": "false"}
Nous pouvons créer plusieurs paramètres d'application : grade_best_type
,
grade_type_a+
, grade_type_a
, grade_type_b+
, grade_type_b
,
grade_type_c
, type de notation des grades.
Étape 4 : Créer les paramètres de l'application
Appelez le contrat @1NewAppParam
pour créer les paramètres de l'application.
Si vous souhaitez modifier les paramètres de l'application, vous pouvez appeler
le contrat @1EditAppParam
.
>callContract @1NewAppParam {"ApplicationId": 47, "Name": "grade_best_type", "Value": "A+", "Conditions": "ContractConditions(\"MainCondition\")"}
>callContract @1NewAppParam {"ApplicationId": 47, "Name": "grade_type_a+", "Value": "{\"max\": 101,\"min\": 90}", "Conditions": "ContractConditions(\"MainCondition\")"}
>callContract @1NewAppParam {"ApplicationId": 47, "Name": "grade_type_a", "Value": "{\"max\": 90,\"min\": 80}", "Conditions": "ContractConditions(\"MainCondition\")"}
>callContract @1NewAppParam {"ApplicationId": 47, "Name": "grade_type_b+", "Value": "{\"max\": 80,\"min\": 70}", "Conditions": "ContractConditions(\"MainCondition\")"}
>callContract @1NewAppParam {"ApplicationId": 47, "Name": "grade_type_b", "Value": "{\"max\": 70,\"min\": 60}", "Conditions": "ContractConditions(\"MainCondition\")"}
>callContract @1NewAppParam {"ApplicationId": 47, "Name": "grade_type_c", "Value": "{\"max\": 60,\"min\": 0}", "Conditions": "ContractConditions(\"MainCondition\")"}
Où grade_best_type
est le meilleur type de notation.
grade_type_a+
est la condition déclenchée par la notation A+
, lorsque le
score est supérieur ou égal à 90 et inférieur à 101, la notation est A+
, les
autres paramètres sont similaires.
Étape 5 : Créer un contrat et le déployer.
Nous créons un contrat pour enregistrer les informations de notes des étudiants et leur note finale pour chaque matière, et nous saisissons la classe et la note de l'étudiant pour chaque matière lors de la saisie des informations.
En fonction des notes saisies pour chaque matière, nous effectuons un calcul de
moyenne pour obtenir la note globale overallScore
et la note finale score
.
Lorsque le contrat est appelé, il créera un enregistrement dans la table de
données que nous venons de créer grade_info
.
D'abord, nous écrivons un contrat et le nommons NewRecord.sim
1 contract NewRecord {
2 data {
3 Student string
4 Grade int
5 Class int
6 Mathematics int
7 Physics int
8 Literature int
9 }
10 func getScore(a b c int) map{
11 var m map
12 var overallScore int
13 overallScore = (a+b+c) / 3
14 m["overallScore"] = overallScore
15 if overallScore >= $gradeTypeABest["min"] && overallScore < $gradeTypeABest["max"] {
16 m["score"] = "A+"
17 }elif overallScore >= $gradeTypeA["min"] && overallScore < $gradeTypeA["max"] {
18 m["score"] = "A"
19 }elif overallScore >= $gradeTypeBBest["min"] && overallScore < $gradeTypeBBest["max"] {
20 m["score"] = "B+"
21 }elif overallScore >= $gradeTypeB["min"] && overallScore < $gradeTypeB["max"] {
22 m["score"] = "B"
23 }elif overallScore >= $gradeTypeC["min"] && overallScore < $gradeTypeC["max"]{
24 m["score"] = "C"
25 }else{
26 m["score"] = "Notset"
27 }
28 return m
29 }
30 func safeJsonDecode(m string) map {
31 var res map
32 if Size(m) > 0 {
33 res = JSONDecode(m)
34 }
35 return res
36 }
37
38 conditions {
39 if Size($Student) == 0 {
40 warning "Student Can not be empty"
41 }
42 if $Class <= 0{
43 warning "Class cannot be less than or equal to zero"
44 }
45 if $Grade <= 0{
46 warning "Grade cannot be less than or equal to zero"
47 }
48 if $Mathematics < 0 {
49 warning "Mathematics cannot be less than zero"
50 }
51 if $Physics < 0 {
52 warning "Physics cannot be less than zero"
53 }
54 if $Literature < 0 {
55 warning "Literature cannot be less than zero"
56 }
57 if $Mathematics > 100 || $Physics > 100 || $Literature > 100{
58 warning "Score cannot exceed 100"
59 }
60 var app map
61 app = DBFind("@1applications").Columns("id,ecosystem").Where({"ecosystem": 18,"name":"GradesRecorder","deleted":0}).Row()
62 if !app {
63 warning LangRes("@1app_not_found")
64 }
65
66 var app_id int
67 app_id = Int(app["id"])
68 $eId = Int(app["ecosystem"])
69 $gradeBestType = AppParam(app_id, "grade_best_type", $eId)
70 $gradeTypeABest = safeJsonDecode(AppParam(app_id, "grade_type_a+", $eId))
71 $gradeTypeA = safeJsonDecode(AppParam(app_id, "grade_type_a", $eId))
72 $gradeTypeBBest = safeJsonDecode(AppParam(app_id, "grade_type_b+", $eId))
73 $gradeTypeB = safeJsonDecode(AppParam(app_id, "grade_type_b", $eId))
74 $gradeTypeC = safeJsonDecode(AppParam(app_id, "grade_type_c", $eId))
75 }
76 action {
77 var m map
78 m = getScore($Mathematics,$Physics,$Literature)
79 var in map
80 in["student"] = $Student
81 in["class"] = $Class
82 in["grade"] = $Grade
83 in["mathematics"] = $Mathematics
84 in["physics"] = $Physics
85 in["literature"] = $Literature
86 in["overall_score"] = m["overallScore"]
87 in["score"] = m["score"]
88 in["created_at"] = $time
89 DBInsert("@"+ Str($eId)+"grade_info", in)
90 }
91 }
Ce qui suit est expliqué par ligne:
- Ligne 2, section des données définit les
paramètres d'entrée
Student
nom de l'étudiant,Grade
classe,Class
classe,Mathematics
score en mathématiques,Physics
score en physique,Literature
score en littérature. - Ligne 10, la fonction getScore, produit un score composite et une note finale basée sur le score de chaque matière.
- Ligne 30, la fonction safeJsonDecode, décode la chaîne JSON et la convertit en map.
- Ligne 38, section conditionnelle.
- Ligne 39, section des opérations.
Comme vous pouvez le voir, lorsque le contrat est appelé, il passe d'abord par
la partie conditionnelle, vérifiant que les paramètres d'entrée du contrat sont
valides, tels que le nom de l'étudiant if Size($Student) == 0 {
est vide
(ligne 39), et s'il l'est, un message d'erreur est renvoyé
"L'étudiant ne peut pas être vide"
(ligne 30). Après avoir vérifié tous les
paramètres d'entrée, à la ligne 61, utilisez
DBFind pour récupérer les informations de la base
de données pour l'application avec l'ecid 18
et le nom de l'application
GradesRecorder
et les informations de l'application avec deleted=0
ne sont
pas supprimées.
Aux lignes 69-74, utilisez AppParam pour
récupérer les paramètres de l'application, par exemple
$gradeBestType = AppParam(app_id, "grade_best_type", $ eId)
(ligne 69).
Si le paramètre de l'application est stocké au format json, tel que
grade_type_a
, vous pouvez vous référer à
$gradeTypeABest = safeJsonDecode(AppParam(app_id, "grade_type_a+", $eId))
, qui
obtiendra le paramètre de l'application par la fonction safeJsonDecode au format
map.
Ensuite, passez à la partie opérationnelle, appelez la fonction getScore pour
obtenir le score composite résultant et la note finale (ligne 10), utilisez une
map pour stocker, ligne 79, définissez une map pour stocker les informations de
réussite de l'étudiant, et DBInsert Insérez les
données dans la table de données @18grade_info
.
Il existe deux façons de créer un contrat, la première consiste à: Tout d'abord, nous écrivons un fichier de paramètres de contrat au format json:
{
"ApplicationId": 47,
"Value": "contract NewRecord {\n data {\n Student string\n Grade int\n Class int\n Mathematics int\n Physics int\n Literature int\n }\n func getScore(a b c int) map{\n var m map\n var overallScore int\n overallScore = (a+b+c) / 3\n m[\"overallScore\"] = overallScore\n if overallScore >= $gradeTypeABest[\"min\"] && overallScore < $gradeTypeABest[\"max\"] {\n m[\"score\"] = \"A+\"\n }elif overallScore >= $gradeTypeA[\"min\"] && overallScore < $gradeTypeA[\"max\"] {\n m[\"score\"] = \"A\"\n }elif overallScore >= $gradeTypeBBest[\"min\"] && overallScore < $gradeTypeBBest[\"max\"] {\n m[\"score\"] = \"B+\"\n }elif overallScore >= $gradeTypeB[\"min\"] && overallScore < $gradeTypeB[\"max\"] {\n m[\"score\"] = \"B\"\n }elif overallScore >= $gradeTypeC[\"min\"] && overallScore < $gradeTypeC[\"max\"]{\n m[\"score\"] = \"C\"\n }else{\n m[\"score\"] = \"Notset\"\n }\n return m\n }\n func safeJsonDecode(m string) map {\n var res map\n if Size(m) > 0 {\n res = JSONDecode(m)\n }\n return res\n }\n\n conditions {\n if Size($Student) == 0 {\n warning \"Student Can not be empty\"\n }\n if $Class <= 0{\n warning \"Class cannot be less than or equal to zero\"\n }\n if $Grade <= 0{\n warning \"Grade cannot be less than or equal to zero\"\n }\n if $Mathematics < 0 {\n warning \"Mathematics cannot be less than zero\"\n }\n if $Physics < 0 {\n warning \"Physics cannot be less than zero\"\n }\n if $Literature < 0 {\n warning \"Literature cannot be less than zero\"\n }\n if $Mathematics > 100 || $Physics > 100 || $Literature > 100{\n warning \"Score cannot exceed 100\"\n }\n var app map\n app = DBFind(\"@1applications\").Columns(\"id,ecosystem\").Where({\"ecosystem\": 18,\"name\":\"GradesRecorder\",\"deleted\":0}).Row()\n if !app {\n warning LangRes(\"@1app_not_found\")\n }\n\n var app_id int\n app_id = Int(app[\"id\"])\n $eId = Int(app[\"ecosystem\"])\n $gradeBestType = AppParam(app_id, \"grade_best_type\", $eId)\n $gradeTypeABest = safeJsonDecode(AppParam(app_id, \"grade_type_a+\", $eId))\n $gradeTypeA = safeJsonDecode(AppParam(app_id, \"grade_type_a\", $eId))\n $gradeTypeBBest = safeJsonDecode(AppParam(app_id, \"grade_type_b+\", $eId))\n $gradeTypeB = safeJsonDecode(AppParam(app_id, \"grade_type_b\", $eId))\n $gradeTypeC = safeJsonDecode(AppParam(app_id, \"grade_type_c\", $eId))\n }\n action {\n var m map \n m = getScore($Mathematics,$Physics,$Literature)\n var in map\n in[\"student\"] = $Student\n in[\"class\"] = $Class\n in[\"grade\"] = $Grade\n in[\"mathematics\"] = $Mathematics\n in[\"physics\"] = $Physics \n in[\"literature\"] = $Literature \n in[\"overall_score\"] = m[\"overallScore\"]\n in[\"score\"] = m[\"score\"]\n in[\"created_at\"] = $time\n DBInsert(\"@\"+ Str($eId)+\"grade_info\", in)\n }\n}",
"Conditions": "ContractConditions(\"@1DeveloperCondition\")"
}
Où ApplicationId
est l'identifiant de l'application, qui doit être échappé
pour les caractères spéciaux, et Conditions
est la permission de modification
du contrat.
Code source du contrat Value
, que nous enregistrons sous le nom
NewRecordParams.json
.
Après avoir rédigé le contrat, nous devons le déployer en appelant
CreateContract@1NewContract
.
1 >>callContract @1NewContract -f=./data/NewRecordParams.json
2 {
3 "block_id": 1262,
4 "hash": "d896f12f685835f6cf71705e1ba...4d8bcc0a1406f7b0b6482b2d230fc",
5 "penalty": 0,
6 "err": "348"
7 }
La ligne suivante est expliquée par ligne :
- Ligne 1 : appeler le contrat
@1NewContract
pour créer le contrat, -f utilise le fichier pour importer le fichierNewRecord.json
nouvellement créé en tant que paramètre du contrat. - Ligne 3 : l'identifiant de bloc généré par la transaction.
- Ligne 4 : le hachage de bloc généré par la transaction.
- Ligne 5 : si l'exécution de la transaction échoue (0 : pas de pénalité, 1 : pénalité).
- Ligne 6 : si l'exécution de la transaction échoue, un message d'erreur est
renvoyé, et si l'identifiant de bloc est renvoyé, le champ d'erreur contient
l'identifiant du contrat qui est
348
.
Deuxième méthode : Le fichier source du contrat enregistré est directement
transmis aux paramètres du contrat dans le format de paramètre nomParamètre
+
-
+ "fichier", nomParamètre-fichier
comme suit :
callContract @1NewContract {"ApplicationId": 47, "Value-file": "NewRecord.sim", "Conditions": "ContractConditions(\"@1DeveloperCondition\ ")"}
Essayons d'appeler le contrat que nous venons de créer.
1 >callContract @18NewRecord {"Student": "tom", "Grade": 1, "Class": 1, "Mathematics": 18, "Physics": 57, "Literature": 93}
2
3 {
4 "block_id": 1263,
5 "hash": "1b964a47fe6c5fd43ea55a752d01edb5ad576432fd6f63315344d87999a0473d",
6 "penalty": 0,
7 "err": ""
8 }
The call is complete, and then we check to see if the data table has saved a record
>getList @18grade_info
{
"count": 1,
"list": [
{
"class": "1",
"created_at": "1683698914109",
"grade": "1",
"id": "9",
"literature": "93",
"mathematics": "18",
"overall_score": "56",
"physics": "57",
"score": "C",
"student": "tom"
}
]
}
Vous pouvez voir qu'il y a déjà un enregistrement dans la table de données,
student
tom avec une note globale de 56 et une note de C.
L'exemple ci-dessus est uniquement à des fins d'étude et de recherche, vous devez modifier les paramètres pertinents en fonction de la situation réelle, tels que la permission d'écriture dans la table de données, la permission de modification de contrat, etc.
Par exemple, si nous voulons spécifier qu'une seule personne peut appeler ce
nouveau contrat et que personne d'autre ne peut l'appeler, nous pouvons définir
un paramètre écologique new_record_account
.
Étape 6 : Créer des paramètres écologiques
Appeler le contrat @1NewParameter
créera l'éco-paramètre new_record_account
dans la table @1parameters
. Si vous avez besoin de modifier l'éco-paramètre,
vous pouvez appeler @1EditParameter
.
>callContract @1NewParameter {"Name": "new_record_account", "Value": "6667782293976713160", "Conditions": "ContractConditions(\"MainCondition\")"}
{
"block_id": 1416,
"hash": "12fc87ce6a70e2fc993ab9ffe623311f1c50edd1157595ce6183c38c93960cae",
"penalty": 0,
"err": "273"
}
Nous créons un paramètre d'écosystème appelé new_record_account
, nous
définissons la valeur sur la cléId 6667782293976713160
, nous modifions les
permissions pour ContractConditions("MainCondition")
, ce qui signifie que le
créateur écologique actuel peut modifier. Lorsque la transaction est exécutée
avec succès, l'identifiant du paramètre écologique dans le champ "err" est
273
.
Étape 7 : ajouter la localisation
Vous pouvez appeler le contrat @1NewLangJoint
pour créer le paramètre de
localisation account_not_access
, qui créera le paramètre dans la table
@1languages
, et vous pouvez modifier le paramètre de localisation via
@1EditLangJoint
.
callContract @1NewLangJoint {"Name": "account_not_access", "LocaleArr": ["en", "ja"], "ValueArr": ["Sorry, you do not have access to this action", "申し訳ありませんが、このアクションにアクセスする権限がありません"]}
Étape 8 Modifier le contrat
Ensuite, nous devons modifier la section conditions
du code source du contrat
en ajoutant le code suivant aux conditions
.
conditions {
if EcosysParam("new_record_account") != $key_id {
warning LangRes("account_not_access")
}
}
Appeler pour modifier le contrat @1EditContract, où Id
est l'identifiant du
contrat, Value
est le code source du contrat.
>callContract @1EditContract {"Id": 348, "Value": "contract NewRecord {\n data {\n Student string\n Grade int\n Class int\n Mathematics int\n Physics int\n Literature int\n }\n func getScore(a b c int) map{\n var m map\n var overallScore int\n overallScore = (a+b+c) / 3\n m[\"overallScore\"] = overallScore\n if overallScore >= $gradeTypeABest[\"min\"] && overallScore < $gradeTypeABest[\"max\"] {\n m[\"score\"] = \"A+\"\n }elif overallScore >= $gradeTypeA[\"min\"] && overallScore < $gradeTypeA[\"max\"] {\n m[\"score\"] = \"A\"\n }elif overallScore >= $gradeTypeBBest[\"min\"] && overallScore < $gradeTypeBBest[\"max\"] {\n m[\"score\"] = \"B+\"\n }elif overallScore >= $gradeTypeB[\"min\"] && overallScore < $gradeTypeB[\"max\"] {\n m[\"score\"] = \"B\"\n }elif overallScore >= $gradeTypeC[\"min\"] && overallScore < $gradeTypeC[\"max\"]{\n m[\"score\"] = \"C\"\n }else{\n m[\"score\"] = \"Notset\"\n }\n return m\n }\n func safeJsonDecode(m string) map {\n var res map\n if Size(m) > 0 {\n res = JSONDecode(m)\n }\n return res\n }\n\n conditions {\n if EcosysParam(\"new_record_account\") != $key_id {\n warning LangRes(\"account_not_access\")\n }\n if Size($Student) == 0 {\n warning \"Student Can not be empty\"\n }\n if $Class <= 0{\n warning \"Class cannot be less than or equal to zero\"\n }\n if $Grade <= 0{\n warning \"Grade cannot be less than or equal to zero\"\n }\n if $Mathematics < 0 {\n warning \"Mathematics cannot be less than zero\"\n }\n if $Physics < 0 {\n warning \"Physics cannot be less than zero\"\n }\n if $Literature < 0 {\n warning \"Literature cannot be less than zero\"\n }\n if $Mathematics > 100 || $Physics > 100 || $Literature > 100{\n warning \"Score cannot exceed 100\"\n }\n var app map\n app = DBFind(\"@1applications\").Columns(\"id,ecosystem\").Where({\"ecosystem\": 18,\"name\":\"GradesRecorder\",\"deleted\":0}).Row()\n if !app {\n warning LangRes(\"@1app_not_found\")\n }\n\n var app_id int\n app_id = Int(app[\"id\"])\n $eId = Int(app[\"ecosystem\"])\n $gradeBestType = AppParam(app_id, \"grade_best_type\", $eId)\n $gradeTypeABest = safeJsonDecode(AppParam(app_id, \"grade_type_a+\", $eId))\n $gradeTypeA = safeJsonDecode(AppParam(app_id, \"grade_type_a\", $eId))\n $gradeTypeBBest = safeJsonDecode(AppParam(app_id, \"grade_type_b+\", $eId))\n $gradeTypeB = safeJsonDecode(AppParam(app_id, \"grade_type_b\", $eId))\n $gradeTypeC = safeJsonDecode(AppParam(app_id, \"grade_type_c\", $eId))\n }\n action {\n var m map \n m = getScore($Mathematics,$Physics,$Literature)\n var in map\n in[\"student\"] = $Student\n in[\"class\"] = $Class\n in[\"grade\"] = $Grade\n in[\"mathematics\"] = $Mathematics\n in[\"physics\"] = $Physics \n in[\"literature\"] = $Literature \n in[\"overall_score\"] = m[\"overallScore\"]\n in[\"score\"] = m[\"score\"]\n in[\"created_at\"] = $time\n DBInsert(\"@\"+ Str($eId)+\"grade_info\", in)\n }\n}"}
Étape 9 Modifier les autorisations de la table de données
Ici, nous devons modifier l'autorisation d'insertion de la table de données,
l'autorisation d'origine ContractConditions("MainCondition")
pour l'écréateur,
et le paramètre de contrat new_record_account
n'est pas l'écréateur.
Donc, il suffit de modifier ContractConditions("MainCondition")
pour spécifier
que le contrat peut opérer sur ContractAccess("@18NewRecord")
.
Appelez le contrat @1EditTable
pour modifier les autorisations de la table de
données.
>callContract @1EditTable {"Name": "@18grade_info", "InsertPerm": "ContractAccess(\"@18NewRecord\")", "UpdatePerm": "ContractConditions(\"MainCondition\")", "ReadPerm": "true", "NewColumnPerm": "ContractConditions(\"MainCondition\")"}
Ensuite, appelez le contrat que vous venez de modifier et créez un nouvel enregistrement.
1 >callContract @18NewRecord {"Student": "tom", "Grade": 1, "Class": 1, "Mathematics": 18, "Physics": 57, "Literature": 93}
2
3 {
4 "block_id": 1435,
5 "hash": "7d4b06d3738133f9c2ec775935478cd2d6c20fd04eca275769afd0f8e6a4f687",
6 "penalty": 1,
7 "err": "{\"type\":\"warning\",\"error\":\"Sorry, you do not have access to this action\"}"
8 }
Vous pouvez voir que le paramètre de localisation que nous venons de définir,
account_not_access
, fonctionne.
Nous avons constaté que l'erreur de permission est signalée, l'utilisateur
actuel n'a pas l'autorisation d'effectuer des opérations. Nous passons au compte
avec l'identifiant de clé 6667782293976713160
et nous pouvons obtenir les
informations de l'utilisateur actuel à l'aide de l'outil en ligne de commande
account info
.
Configurez le fichier de configuration de l'outil en ligne de commande
config.yml et passez au compte avec l'identifiant de clé 6667782293976713160
.
Une fois la configuration terminée, appelez à nouveau le contrat.
>callContract @18NewRecord {"Student": "tini", "Grade": 1, "Class": 3, "Mathematics": 69, "Physics": 89, "Literature": 98}
{
"block_id": 1436,
"hash": "93327dafb7bae9f9f66718eb87020a7bca4c00060f4bd0a243b49eea304c52e6",
"penalty": 0,
"err": ""
}
L'appel est terminé, interrogeant la table de données via
getList @18grade_info
, et le résultat est conforme aux attentes.
Nous espérons que cet article vous a aidé à en savoir plus sur le fonctionnement
du réseau IBAX et sur la façon d'écrire un code Needle
clair et sécurisé.
Déployer une application à l'aide d'outils en ligne de commande
Dans ce tutoriel, vous apprendrez comment :
Avant de commencer ce tutoriel, vous devez avoir votre propre application et connaître le concept d'écosystème et d'application. Vous pouvez vous référer au Guide de démarrage.
Nous importerons l'application sur la blockchain IBAX via l'outil en ligne de commande ibax-cli. Exporter une application.
Exporter l'application
Appeler account info
pour interroger les informations du compte actuel, ici le
login ecid est 9
, appeler la commande getList
pour interroger les
applications associées à l'ecid actuel.
$ ibax-cli console
Welcome to the IBAX console!
To exit, press ctrl-d or type exit
>account info
{
"public_key": "04d11ea197fe23152562c6f54c4...889c074dfd9080099982d8b2d4d100315e1cebc7",
"ecosystem_id": 9,
"key_id": 6660819...78795186,
"account": "0666-0819-...-7879-5186"
}
>getList @1applications -w={"ecosystem": 9}
{
"count": 6,
"list": [
{
"conditions": "true",
"deleted": "0",
"ecosystem": "9",
"id": "36",
"name": "testapp",
"uuid": "00000000-0000-0000-0000-000000000000"
}
...
]
}
Nous pouvons voir que l'écosystème actuel compte 6 applications. Nous utilisons
la commande export
pour exporter l'application avec l'id
de 36
.
>export 36 -f=./data.json
{
"name": "./data.json",
"type": "application/json",
"value": ""
}
Le paramètre -f ici enregistre l'application exportée dans le fichier
data.json
dans le répertoire actuel. Si aucun paramètre -f n'est spécifié, les
données de l'application seront affichées dans le terminal de commande.
La commande export
encapsule les étapes pour exporter une application. Vous
pouvez utiliser la commande ci-dessus pour exporter une application, ou suivre
les étapes suivantes, comme suit :
Appeler le contrat @1ExportNewApp
pour exporter une nouvelle application
générera un enregistrement dans la table 1_buffer_data
pour l'application
exportée.
>callContract @1ExportNewApp {"ApplicationId": 36}
Appelez le contrat @1Export
pour exporter l'application, recherchez
l'application sélectionnée dans la table 1_buffer_data
, et exportez toutes les
ressources de l'application vers la chaîne JSON générée.
La chaîne JSON générée sera écrite dans la table 1_binaries
de l'écosystème
actuel.
>callContract @1Export
Interrogez les données dans la table 1_binaries
avec la commande getList
.
>getList @1binaries -w={"name": "export", "account": "0666-0819-...-7879-5186", "ecosystem": 9, "app_id": 36} -l=1 -c="id,hash"
{
"count": 1,
"list": [
{
"hash": "8542cb57b77e0ae2c...92c3e05dbbe35ab646789be5b8ba8",
"id": "14"
}
]
}
Obtenez l'identifiant binaire et le hachage.
Appelez la commande binaryVerify
pour exporter le fichier binaire.
>binaryVerify 14 8542cb57b77e0ae2c...92c3e05dbbe35ab646789be5b8ba8 -f=./data.json
{
"name": "./data.json",
"type": "application/json",
"value": ""
}
Importer l'application
Utilisez la commande import
pour importer une application, avec le paramètre
-f
pour spécifier le fichier d'application à importer.
$ ibax-cli console
Welcome to the IBAX console!
To exit, press ctrl-d or type exit
>import -f . /data.json
The import
command encapsulates the steps to import an application, you can
use the above command to import an application
Or use the following steps, which, for ease of study and research, are as follows:
- Étape 1 : Appeler le contrat
@1ImportUpload
pour importer une nouvelle application générera un enregistrement dans la table1_buffer_data
pour l'application exportée.@1ImportUpload
Le paramètre du contratData
estfile
type. Il contient les mots-clésName
pour le nom du fichier (chaîne de caractères),MimeType
pour le type de fichier (chaîne de caractères),Body
pour le contenu du fichier ([]byte). Vous devez encoder en base64 les données du fichier de l'application et les passer dansBody
, vous pouvez utiliser la commandebase64Encode
pour les encoder en base64.
>base64Encode -f=./data.json
Encode:ewoJIm5hbWUiOiAid...CQkJIlR5cGUiOiAiY29udHJhY3RzIiwKCQkJIk5hbWUiOiAiSGVsbG9Xb3JsZCIsCgkJCSJWYWx1ZSI6...
>callContract @1ImportUpload {"Data": {"Name": "filename", "MimeType": "mimeType", "Body": "ewoJIm5hbWUiOiAid...CQkJIlR5cGUiOiAiY29udHJhY3RzIiwKCQkJIk5hbWUiOiAiSGVsbG9Xb3JsZCIsCgkJCSJWYWx1ZSI6..."}}
- Étape 2 : Après que l'appel est terminé, utilisez la commande
getList
pour interroger les données dans la table1_buffer_data
.
>getList @1buffer_data -w={"key": "import", "account": "0666-0819-xxxx-7879-5186", "ecosystem": 19} -l=1 -c=value->'data'
{
"count": 1,
"list": [
{
"id": "22",
"value.data": "[{"Data": "[a,b]"}, {"Data": "[c,d]"}]"
}
]
}
- Étape 3 : Assemblez les données de value.data->Data dans un tableau
unidimensionnel, [a,b,c,d]. Ensuite, créez un fichier de paramètres de contrat
importParams.json
, avec le contenu suivant :
{ "Data": "[a,b,c,d]" }
- Étape 4 : Appelez le contrat
@1Import
pour importer les données de l'application.
>callContract @1Import -f=./importParams.json
Configuration écologique à l'aide d'un outil en ligne de commande
Dans ce tutoriel, vous apprendrez comment :
Avant de commencer ce tutoriel, vous devez avoir votre propre application et connaître le concept d'écosystème et d'application. Vous pouvez vous référer au Guide de démarrage.
Nous allons effectuer la configuration écologique sur la blockchain IBAX via l'outil en ligne de commande ibax-cli.
Postuler pour rejoindre l'écosystème
Nous pouvons appeler le contrat @1MembershipRequest
pour demander à rejoindre
l'écosystème.
L'exemple suivant:
>callContract @1MembershipRequest {"EcosystemId": 19}
Demande de rejoindre l'écosystème avec l'identifiant écologique 19
, le contrat
@1MembershipRequest
impose une restriction sur l'appel de l'écosystème, seul
l'écosystème de base peut être appelé.
Lorsque la demande est acceptée, le gestionnaire de l'écosystème cible recevra une demande et elle ne sera considérée comme faisant partie de l'écosystème cible que lorsque la demande sera approuvée par le gestionnaire de l'écosystème.
Bien sûr, si l'écosystème cible est public, vous pouvez le rejoindre directement.
Ajouter des membres de l'écosystème
Lorsque l'écosystème vient d'être créé, le seul membre de l'écosystème est le
créateur de l'écosystème. Lorsque vous souhaitez inviter d'autres membres à
rejoindre, vous devez connaître la clé publique de la personne invitée, puis
appeler le contrat @1MembershipAdd
pour ajouter des membres.
>callContract @1MembershipAdd {"Keys": "04f2c1780ca0aa0f343d0e541c77811...3b0d5bf3a9903253aad6e78c966b5f91ffb32703884020"}
Si l'écosystème est public et permet à n'importe qui de rejoindre, vous pouvez
définir le paramètre de l'écosystème free_membership
= 1, qui n'est pas public
par défaut.
Une fois configuré, vous n'avez pas besoin d'être approuvé pour rejoindre votre écosystème.
>callContract @1NewParameter {"Name": "free_membership", "Value": "1", "Conditions": "ContractConditions(\"MainCondition\")"}
Si vous ne définissez pas le paramètre free_membership
, lorsque d'autres
membres demandent à rejoindre votre écosystème, vous recevrez une notification
de demande.
Appelez l'application d'approbation du contrat @1MembershipDecide
, les
paramètres du contrat NotificId
sont l'identifiant de la notification,
'Accept' est la marque de résolution, la marque de résolution 1
est acceptée.
>callContract @1MembershipDecide {"NotificId": 6, "Accept": 1}
Blocage des comptes
Appeler le contrat @1DeleteMember
pour geler le compte, notez que cette
opération ne peut pas être restaurée.
>callContract @1DeleteMember {"MemberAccount": "1539-2715-xxxx-1679-5385"}
Gestion des rôles
- Création d'un nouveau rôle
- Ajouter un membre au rôle
- Supprimer un membre du rôle
- Modifier le gestionnaire du rôle
- Supprimer le rôle
Création d'un nouveau rôle
Appeler le contrat @1RolesCreate
pour créer un nouveau rôle, nom du rôle
student
, type 2
(1 - Assignable 2 - Élu par vote 3 - Système).
>callContract @1RolesCreate {"Name": "student", "Type": 2}
{
"block_id": 1685,
"hash": "5321f2231a...d0d80158b62766395f14d0ff7",
"penalty": 0,
"err": "21"
}
Le résultat de retour contient l'identifiant de rôle 21
.
Ajout de membres de rôle
Il existe deux méthodes, la première méthode consiste à ce que le membre de
l'écosystème initie la demande d'application en appelant le contrat
@1RolesRequest
pour demander à être ajouté en tant que membre du rôle, où
Rid
est l'identifiant du rôle.
>callContract @1RolesRequest {"Rid": 21}
Dans la deuxième méthode, le gestionnaire de rôles attribue des membres de rôle,
et le gestionnaire de rôles appelle le contrat @1RolesAssign
pour ajouter des
membres au rôle.
>callContract @1RolesAssign {"MemberAccount": "0666-7782-xxxx-7671- 3160", "Rid": 21}
Supprimer les membres du rôle
Tout d'abord, nous voyons quels membres un rôle possède, que nous pouvons interroger via getList, comme suit:
>getList @1roles_participants -w={"ecosystem": 18, "role->id": "21", "deleted": 0}
{
"count": 3,
"list": [
{
"appointed": "{\"account\": \"1273-2644-xxxx-5846-6598\", \"image_id\": \"0\", \"member_name\": \"founder\"}",
"date_created": "1684916023",
"date_deleted": "0",
"deleted": "0",
"ecosystem": "18",
"id": "21",
"member": "{\"account\": \"1273-2644-xxxx-5846-6598\", \"image_id\": \"0\", \"member_name\": \"founder\"}",
"role": "{\"id\": \"20\", \"name\": \"teacher\", \"type\": \"1\", \"image_id\": \"0\"}"
}
...
]
}
Où la condition where
ecosystem
spécifie l'écosystème, role->id
spécifie
l'identifiant du rôle et deleted
: 0 spécifie non supprimé.
Nous pouvons voir que nous avons 3 lignes, si nous voulons supprimer le rôle
avec le membre 1273-2644-xxxx-5846-6598
, c'est-à-dire le rôle avec l'id
de
21
.
Les administrateurs peuvent appeler le contrat @1RolesUnassign
pour supprimer
les membres du rôle, comme suit:
>callContract @1RolesUnassign {"RowId": 21}
Modifier le gestionnaire de rôles
Regardons les rôles écologiques actuels :
>getList @1roles -w={"ecosystem": 18}
{
"count": 5,
"list": [
{
"company_id": "0",
"creator": "{\"account\": \"1273-2644-xxxx-5846-6598\", \"image_id\": \"0\", \"member_name\": \"founder\"}",
"date_created": "1684910917",
"date_deleted": "0",
"default_page": "",
"deleted": "0",
"ecosystem": "18",
"id": "20",
"image_id": "0",
"role_name": "teacher",
"role_type": "1",
"roles_access": "[]"
}
...
]
}
où roles_access
est le rôle administratif pour le rôle actuel, qui est un
tableau et peut en avoir plusieurs.
Nous ajoutons un rôle administratif au rôle teacher
en appelant le contrat
@1RolesAccessManager
, où les paramètres du contrat sont Action
l'opérateur
administratif (clean
, remove
, add
), Rid
l'ID du rôle à gérer,
ManagerRid
l'ID du gestionnaire de rôle.
>callContract @1RolesAccessManager {"Action": "add", "Rid": 20, "ManagerRid": 13}
{
"block_id": 1745,
"hash": "e2eb8ff0dc309ec7652db...bbbe58bca4ca574804e46c2f63653eb73104",
"penalty": 0,
"err": ""
}
Supprimer le rôle
Nous pouvons appeler le contrat @1RolesDelete
pour supprimer des rôles, où les
paramètres du contrat Rid
sont l'ID du rôle à gérer et Ops
est l'opérateur
(D
pour supprimer, R
pour restaurer).
>callContract @1RolesDelete {"Rid": 24, "Ops": "D"}
{
"block_id": 1785,
"hash": "1ebf99a04f504fc3d2...4ecfbdfc419bf3dbf39df0013dca913f844",
"penalty": 0,
"err": ""
}
Émission de jeton
Créer un écosystème
Créez un écosystème, appelez le contrat @1NewEcosystem
.
>callContract @1NewEcosystem {"Name": "Test Ecosystem"}
{
"block_id": 1787,
"hash": "384f35ef93243c9dd4f53b9298873b356b25b31cf7c6a6be7600ee7694d77006",
"penalty": 0,
"err": "21"
}
Ensuite, nous modifions la configuration de l'outil en ligne de commande pour se connecter à cet écosystème nouvellement créé : "21".
Installation des applications de base
Appelez le contrat pour installer l'application de base, comme suit :
1 >callContract @1PlatformAppsInstall
2 >callContract @1RolesInstall
3 >callContract @1AppInstall {"ApplicationId": 5}
4 >callContract @1AppInstall {"ApplicationId": 6}
Ligne 1, installez l'application de plateforme ;
Ligne 2, installez le rôle par défaut ;
Ligne 3-4, installez l'application de configuration écologique et d'émission de
jetons, où l'ID de l'application 5,6
peut être consulté via getList comme suit
:
>getList @1applications -w={"ecosystem": 1, "$or": [{"name": "Token emission"},{"name": "Ecosystems catalog"}]} -c="name,ecosystem"
{
"count": 2,
"list": [
{
"ecosystem": "1",
"id": "5",
"name": "Token emission"
},
{
"ecosystem": "1",
"id": "6",
"name": "Ecosystems catalog"
}
]
}
Émission de jetons
Parce qu'il s'agit d'un nouvel écosystème, vous devez configurer l'émission de
jetons, appelez le contrat @1TeSettings
pour spécifier les rôles pouvant
émettre des jetons.
>callContract @1TeSettings {"RoleDeveloper": 30}
Où RoleDeveloper
est l'identifiant actuel du rôle écologique, qui peut être
obtenu via la table de données @1roles
.
Émission de jetons Appeler le contrat @1NewToken
pour émettre des jetons.
>callContract @1NewToken {"Symbol": "TEST", "Name": "TEST Coin", "Amount": "10000000000000000" ,"Digits": "12"}
Où les paramètres du contrat Symbol
sont le symbole du jeton, Name
est le
nom du jeton, Amount
est le montant total et Digits
est la précision.
Émission de jetons
>callContract @1TeEmission {"Amount": 1000000000000}
Détruire les jetons
>callContract @1TeBurn {"Amount": 1000000000000}
Incrément de jeton par défaut et destruction de jeton sont autorisés, vous
pouvez les désactiver en utilisant @1TeChange
, où TypeChange
est le type
(emission
pour l'incrément, withdraw
pour la destruction).
Value
est l'état activé/désactivé (1
activé, 2
désactivé), par exemple:
Ajouts fermés.
Note: Ne peut pas être activé après la fermeture.
>callContract @1TeChange {"TypeChange": "emission", "Value": 2}
Désactiver la destruction, si vous souhaitez réactiver la destruction, il
suffit de définir la valeur de Value
sur 1
.
>callContract @1TeChange {"TypeChange": "withdraw", "Value": 2}
Déduction de l'écosystème
Avant de mettre en place des déductions écologiques, vous devez comprendre le modèle de frais IBAX, qui peut être trouvé dans le livre blanc.
Nous commençons par définir l'adresse du portefeuille écologique, appelons le
contrat @1EditParameter
et modifions les paramètres écologiques.
>callContract @1EditParameter {"Id": 334, "Value": "1273-2644-xxxx-5846-6598"}
Où Id
est l'identifiant du paramètre ecosystem_wallet
de l'ecowallet, qui
peut être interrogé comme suit :
>getList @1parameters -w={"ecosystem": 22, "name": "ecosystem_wallet"}
La valeur Value
est l'adresse de l'ecowallet qui sera liée, et le contrat
génère les frais de gaz, qui sont payés par cette adresse. L'adresse doit avoir
suffisamment de jetons dans l'écosystème actuel et doit être approuvée par
l'adresse liée avant que la modification ne soit réussie.
Appeler le contrat @1EcoFeeModeManage
pour configurer la déduction
multi-écologique, comme suit :
>callContract @1EcoFeeModeManage {"FollowFuel": 0.01, "CombustionFlag": 1, "VmCostFlag": 2, "VmCostConversionRate": 100, "StorageConversionRate": 100, "StorageFlag": 2, "ExpediteFlag": 1}
Où les champs de paramètres du contrat sont définis comme suit :
- Le paramètre
FollowFuel
est un multiple du taux d'éco-suivi 1. CombustionFlag
indique s'il faut activer la combustion des frais de gaz d'éco-échange, 1 - non, 2 - oui.CombustionPercent
est le pourcentage de combustion, uniquement valable lorsque la combustion des frais de gaz est activée, prend des valeurs de 1 à 100, 0 lorsque ce n'est pas activé.VmCostFlag
est le drapeau des coûts de VM, définissant le paiement direct ou par procuration, 1 - paiement direct, 2 - paiement par procuration.StorageFlag
est le drapeau des frais de stockage, définissant le paiement direct ou par procuration, 1 - paiement direct, 2 - paiement par procuration.ExpediteFlag
est le drapeau des frais d'expédition accélérée, définissant le paiement direct ou par procuration, 1 - paiement direct, 2 - paiement par procuration.VmCostConversionRate
est le taux de conversion des coûts de la machine virtuelle, avec 2 décimales, uniquement valable pour les paiements par procuration, supérieur à zéro.StorageConversionRate
est le taux de conversion des coûts de stockage, avec 2 décimales, uniquement valable pour les paiements par procuration, supérieur à zéro.
Si vous utilisez les paramètres ci-dessus, tous les frais de transaction encourus par les utilisateurs invoquant des contrats au sein de l'écosystème seront payés par le portefeuille écologique de la configuration écologique actuelle.
Tous les utilisateurs n'ont besoin de payer que les frais de gaz encourus au sein de l'écosystème. Bien sûr, vous pouvez ajuster les paramètres de coût selon vos besoins réels.
Écosystème de gouvernance DAO
Avant de modifier vers un écosystème de gouvernance DAO, vous devez vous assurer que l'écosystème actuel a émis des jetons, et après la modification vers un écosystème de gouvernance DAO, toutes les propositions de l'écosystème seront soumises au vote des membres du comité de gouvernance.
Le Conseil de gouvernance DAO n'est plus géré uniquement par les développeurs de l'écosystème, mais les 50 principaux représentants des détenteurs de l'écosystème sont élus.
Call the @1EditControlMode
contract to change the eco governance mode to DAO
governance mode.
>callContract @1EditControlMode {"Value": 2}
Où le paramètre Value
1
représente le modèle du créateur et 2
représente
le modèle de gouvernance DAO.
Nous pouvons essayer de créer une application.
>callContract @1NewApplication {"Name": "testApp", "Conditions": "ContractConditions(\"@1DeveloperCondition\")"}
À ce stade, une proposition de gouvernance DAO est générée et votée par le Conseil de gouvernance de la DAO avant la création de l'application. Une proposition valide nécessite un taux d'approbation de 68% sur 75% des votes exprimés.
Le champ d'application de la gouvernance DAO comprend :
- Ajouter, supprimer et modifier des applications, des contrats, des pages, des extraits de code, des onglets, des menus, des paramètres d'application, des tables de données et des champs.
- Modifier le multilingue.
- Changer le modèle de DAO et de créateur.
- Modifier les paramètres écologiques.
- Rôle, assigner ou supprimer des membres de rôle.
- Émettre une monnaie de destruction supplémentaire.
- Modifier les paramètres de la plateforme.
- Modifier les informations écologiques.
- Modification des contrats différés.
- Modifier le modèle de vote.
Déployer des applications à l'aide d'un outil d'emballage d'applications
Avant de commencer ce tutoriel, vous devez télécharger Outil de conditionnement d'application IBAX. Nous devons utiliser cet outil pour empaqueter l'application IBAX.
Nous devons stocker les fichiers de l'application selon la structure de répertoire suivante :
- APP Name
- app_params
params1.csv
params2.csv
...
- contracts
contract1.sim
contract2.sim
...
- tables
tableName1.json
tableName2.json
...
config.json
Comme indiqué ci-dessous:
airdrop$ ls *
config.json
app_params:
dedicated_account.csv lock_percent.csv per_period_sec.csv period_count.csv
contracts:
AddAirdrop.sim ClaimAirdrop.sim SpeedAirdrop.sim
tables:
airdrop_info.json
Le répertoire app_params
stocke le fichier des paramètres de l'application,
nommé en utilisant le nom du paramètre + le format de fichier .csv
, le contenu
du fichier étant la valeur du paramètre.
Le répertoire contracts
contient les contrats, au format de fichier .sim
, et
le contenu du fichier est le code source du contrat.
Le répertoire tables
contient la structure de la table de données de
l'application au format de fichier json
, comme suit:
[
{
"name": "account",
"conditions": "{\"read\": \"true\", \"update\": \"ContractConditions(\"MainCondition\")\"}",
"type": "varchar"
},
{ "name": "balance_amount", "conditions": "true", "type": "money" },
{ "name": "stake_amount", "conditions": "true", "type": "money" },
{ "name": "surplus", "conditions": "true", "type": "number" },
{ "name": "total_amount", "conditions": "true", "type": "money" }
]
name
est le nom du champ du tableau de données, conditions
est la permission
du champ du tableau de données, et type
est le type de champ.
À l'étape 1, nous générons un fichier config.json et le sauvegardons dans le répertoire airdrop avec le contenu suivant :
{
"name": "Airdrop",
"conditions": "ContractConditions(\"@1MainCondition\")"
}
Là où name
est le nom de l'application, conditions
: est l'autorisation de
modifier l'application, puis l'enregistrer dans le répertoire airdrop.
Étape 2, empaquetez l'application, la commande suivante générera l'application
airdrop.json
dans le répertoire actuel. Si vous modifiez le contrat ou les
paramètres de l'application, vous devez reconditionner l'application.
$ ./app-tool airdrop/
Nous pouvons importer l'application via l'outil en ligne de commande command line tool comme suit :
Utilisez la commande import
pour importer une application, avec le paramètre
-f
pour spécifier le fichier d'application à importer.
$ ibax-cli console
Welcome to the IBAX console!
To exit, press ctrl-d or type exit
>import -f ./airdrop.json
Bien sûr, si vous avez une application, vous pouvez également générer la structure complète du répertoire avec la commande suivante:
$ app-tool.exe airdrop.json