Programme d'affiliation décentralisé et open source sur la blockchain Waves

Un programme d'affiliation décentralisé sur la blockchain Waves, mis en œuvre dans le cadre d'une subvention Waves Labs par l'équipe Bettex.

Le message n'est pas de la publicité! Le programme est open source, son utilisation et sa distribution sont gratuites. L'utilisation du programme stimule le développement d'applications dApp et favorise généralement la décentralisation, ce qui profite à chaque internaute.

Programme d'affiliation décentralisé et open source sur la blockchain Waves

La dApp présentée pour les programmes d'affiliation est un modèle pour les projets qui incluent l'affiliation dans leurs fonctionnalités. Le code peut être utilisé comme modèle de copie, comme bibliothèque ou comme ensemble d'idées pour la mise en œuvre technique.

En termes de fonctionnalités, il s'agit d'un système d'affiliation régulier qui met en œuvre l'inscription auprès d'un parrain, l'accumulation à plusieurs niveaux de récompenses pour les parrainages et la motivation pour l'inscription dans le système (cashback). Le système est une dApp « pure », c’est-à-dire que l’application Web interagit directement avec la blockchain, sans avoir son propre backend, base de données, etc.

Techniques utilisées qui peuvent également être utiles dans de nombreux autres projets :

  • Endettement d'un compte intelligent avec remboursement immédiat (au moment de l'appel il n'y a pas de tokens sur le compte pour payer l'appel, mais ils y apparaissent à la suite de l'appel).
  • PoW-captcha - protection contre les appels automatisés à haute fréquence vers les fonctions du compte intelligent - analogue au captcha, mais grâce à la preuve de l'utilisation des ressources informatiques.
  • Recherchez des clés de données à l'aide d'un modèle.

La candidature se compose de :

  • code de compte intelligent dans le langage ride4dapps (qui, comme prévu, est fusionné dans le compte intelligent principal pour lequel la fonctionnalité d'affiliation doit être implémentée) ;
  • js wrapper qui implémente un niveau d'abstraction sur l'API WAVES NODE REST ;
  • code sur le framework vuejs, qui est un exemple d'utilisation de la bibliothèque et du code RIDE.

Décrivons toutes les fonctionnalités répertoriées.

Appeler un compte intelligent pour les dettes avec remboursement immédiat

L’appel d’InvokeScript nécessite le paiement de frais depuis le compte initiant la transaction. Ce n'est pas un problème si vous réalisez un projet pour les geeks de la blockchain qui ont un certain nombre de jetons WAVES sur leur compte, mais si le produit est destiné à être utilisé par le grand public, cela devient un problème sérieux. Après tout, l'utilisateur doit s'occuper d'acheter des jetons WAVES (ou un autre actif approprié pouvant être utilisé pour payer des transactions), ce qui augmente la barrière déjà considérable à l'entrée dans le projet. Nous pouvons distribuer un actif aux utilisateurs qui pourront payer pour les transactions et faire face au risque de leur utilisation abusive lorsque des systèmes automatisés seront créés pour extraire un actif liquide de notre système.

Ce serait très pratique s'il était possible d'appeler InvokeScript « aux frais du destinataire » (le compte intelligent sur lequel le script est installé), et une telle possibilité, bien que pas évidente, existe.

Si dans InvokeScript vous effectuez un ScriptTransfer à l'adresse de l'appelant, qui compense les jetons de frais dépensés, alors un tel appel réussira, même si au moment de l'appel il n'y avait aucun actif sur le compte appelant. Cela est possible car la vérification de la quantité suffisante de jetons est effectuée après l'appel de la transaction, plutôt qu'avant, de sorte que les transactions peuvent être effectuées à crédit, sous réserve d'un remboursement immédiat.

ScriptTransfer(i.caller, i.fee, unité)

Le code ci-dessous rembourse les frais dépensés en utilisant les fonds du compte intelligent. Pour se protéger contre une utilisation abusive de cette fonctionnalité, il est nécessaire de vérifier que l'appelant dépense les frais dans l'actif requis et dans des limites raisonnables :

func checkFee(i:Invocation) = {
if i.fee > maxFee then throw(“unreasonable large fee”) else
if i.feeAssetId != unit then throw(“fee must be in WAVES”) else true
}

De plus, pour se protéger contre le gaspillage de fonds malveillant et insensé, une protection automatique des appels (PoW-captcha) est requise.

PoW-captcha

L'idée même du captcha de preuve de travail n'est pas nouvelle et a déjà été mise en œuvre dans divers projets, notamment ceux mis en œuvre sur la base de WAVES. L'idée est que pour effectuer une action qui consomme les ressources de notre projet, l'appelant doit également dépenser ses propres ressources, ce qui rend une attaque d'épuisement des ressources assez coûteuse. Pour une validation très simple et peu coûteuse que l'expéditeur de la transaction a résolu le problème PoW, il existe une vérification de l'identifiant de la transaction :

if take(toBase58String(i.transactionId), 3) != « 123 » then throw (« la preuve de travail a échoué ») else

Afin d'effectuer une transaction, l'appelant doit sélectionner de tels paramètres pour que son code base58 (id) commence par les chiffres 123, ce qui correspond en moyenne à quelques dizaines de secondes de temps processeur et est généralement raisonnable pour notre tâche. Si un PoW plus simple ou plus complexe est requis, la tâche peut alors être facilement modifiée de manière évidente.

Requête de clés de données à l'aide d'un modèle

Afin d'utiliser la blockchain comme base de données, il est essentiel de disposer d'outils API pour interroger la base de données sous forme de clé basée sur des modèles. Une telle boîte à outils est apparue début juillet 2019 sous la forme d'un paramètre ?allumettes à la demande de l'API REST /adresses/données?matches=regexp. Désormais, si nous avons besoin d'obtenir plusieurs clés d'une application Web et non pas toutes les clés à la fois, mais seulement un groupe, nous pouvons alors effectuer une sélection par nom de clé. Par exemple, dans ce projet, les transactions de retrait sont codées comme

withdraw_${userAddress}_${txid}

qui permet d'obtenir une liste des transactions de retrait de fonds pour n'importe quelle adresse donnée à l'aide du modèle :

?matches=withdraw_${userAddress}_.*

Examinons maintenant les composants de la solution finale.

Code Vuejs

Le code est une démo fonctionnelle proche du projet réel. Il implémente la connexion via Waves Keeper et fonctionne avec la bibliothèque affilié.js, avec laquelle il enregistre l'utilisateur dans le système, interroge les données de transaction et vous permet également de retirer les fonds gagnés sur le compte de l'utilisateur.

Programme d'affiliation décentralisé et open source sur la blockchain Waves

Code pour RIDE

Comprend les fonctions d’enregistrement, de financement et de retrait.

La fonction d'enregistrement enregistre un utilisateur sur le système. Il a deux paramètres : referer (adresse du référent) et le paramètre salt, qui n'est pas utilisé dans le code de fonction, qui est nécessaire pour sélectionner l'identifiant de transaction (tâche PoW-captcha).

La fonction (comme d'autres fonctions de ce projet) utilise la technique de l'appel de dette, le résultat de la fonction est de financer le paiement de frais pour l'appel de cette fonction. Grâce à cette solution, un utilisateur qui vient de créer un portefeuille peut immédiatement travailler avec le système et n'a pas à se soucier d'acheter ou de recevoir un actif lui permettant de payer des frais de transaction.

Le résultat de la fonction d'enregistrement est deux enregistrements :

${owner)_referer = referer
${referer}_referral_${owner} = owner

Cela permet des recherches avant et arrière (le référent d'un utilisateur donné et toutes les références d'un utilisateur donné).

La fonction de fonds est plutôt un modèle pour développer de réelles fonctionnalités. Dans sa forme présentée, il prend tous les fonds transférés par la transaction et les distribue aux comptes des référents de niveaux 1, 2, 3, au compte « cashback » et au compte « change » (tout ce qui reste lors de la distribution aux précédents les comptes vont ici).

Le cashback est un moyen de motiver l'utilisateur final à participer au système de parrainage. L'utilisateur peut retirer la partie de la commission payée par le système sous forme de « cashback » au même titre que les récompenses de parrainage.

Lors de l'utilisation d'un système de référencement, la fonction du fonds doit être modifiée et intégrée dans la logique principale du compte intelligent sur lequel le système fonctionnera. Par exemple, si une récompense de parrainage est payée pour un pari effectué, alors la fonction de fonds doit être intégrée dans la logique dans laquelle le pari est placé (ou une autre action ciblée est effectuée pour laquelle la récompense est payée). Trois niveaux de récompenses de parrainage sont codés dans cette fonction. Si vous devez créer plus ou moins de niveaux, cela est également corrigé dans le code. Le pourcentage de récompense est défini par les constantes de niveau 1 à 3 ; dans le code, il est calculé comme suit : montant * niveau / 1000, c'est-à-dire que la valeur 1 correspond à 0,1% (cela peut également être modifié dans le code).

L'appel de la fonction modifie le solde du compte et crée également des entrées à des fins de journalisation du formulaire :

fund_address_txid = address:owner:inc:level:timestamp
Для получения timestamp (текущего времени) используется такая вот связка
func getTimestamp() = {
let block = extract(blockInfoByHeight(height))
toString(block.timestamp)
}

Autrement dit, l’heure de la transaction est l’heure du bloc dans lequel elle se trouve. C'est plus fiable que d'utiliser l'horodatage de la transaction elle-même, d'autant plus qu'il n'est pas disponible depuis l'appelable.
La fonction de retrait affiche toutes les récompenses accumulées sur le compte de l'utilisateur. Crée des entrées à des fins de journalisation :

# withdraw log: withdraw_user_txid=amount:timestamp

Application

La partie principale de l'application est la bibliothèque affilié.js, qui constitue un pont entre les modèles de données d'affiliation et l'API WAVES NODE REST. Implémente un niveau d'abstraction indépendant du framework (n'importe lequel peut être utilisé). Les fonctions actives (enregistrement, retrait) supposent que Waves Keeper est installé sur le système ; la bibliothèque elle-même ne le vérifie pas.

Méthodes mises en œuvre :

fetchReferralTransactions
fetchWithdrawTransactions
fetchMyBalance
fetchReferrals
fetchReferer
withdraw
register

La fonctionnalité des méthodes ressort clairement des noms ; les paramètres et les données renvoyées sont décrits dans le code. La fonction d'enregistrement nécessite des commentaires supplémentaires - elle démarre un cycle de sélection de l'identifiant de transaction pour qu'il commence à 123 - c'est le PoW-captcha décrit ci-dessus, qui protège contre les enregistrements de masse. La fonction trouve une transaction avec l'identifiant requis, puis la signe via Waves Keeper.

Le programme d'affiliation DEX est disponible sur GitHub.com.

Source: habr.com

Ajouter un commentaire