
Përshëndetje të gjithëve!
Në Këtu kemi shqyrtuar në detaje se si të krijojmë dhe punojmë me një dApp (aplikacion decentralizuar) në .
Tani le të testojmë pak atë që kemi shqyrtuar .
Hapi 3. Testimi i llogarisë dApp

ĂfarĂ« shqetĂ«simesh bien menjĂ«herĂ« nĂ« sy me Alice? dApp Llogaria?
E para:
Boob dhe Cooper mund të dërgojnë aksidentalisht fonde në adresën e dApp me anë të një transfer transaksioni dhe kështu nuk do të mund të kthejnë ato mbrapsht.Së dyti:
Ne nuk i kufizojmë Alice në tërheqjen e fondeve pa miratimin e Boob ose (dhe) Cooper. Vini re, për të verifikuar, të gjitha transaksionet nga Alice do të ekzekutohen.
Le të rregullojmë të dytën, duke ndaluar Alice transfer transaksionet. Bëjmë deploy skenarin e rregulluar:

ïżŒ
Provojmë të tërheqim monedha nga dApp Alice me nënshkrimin e saj. Marrim një gabim:

Provojmë të tërheqim përmes withdraw:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"withdraw",args:[{type:"integer", value: 1000000}]}, payment: []}))Skenari funksionon dhe me pikën e dytë ne u sqaruam!
Hapi 4. Krijojmë DAO me votim
Fatkeqësisht, në gjuhën RIDE akoma nuk janë parashikuar mundësitë për të punuar me koleksione (fjalorë-fjalorësh, iteratorë, reduktues dhe të tjera). Megjithatë, për çdo operacion me koleksione të thjeshta çelës-vlerë ne mund të krijojmë një sistem pune me vargje, përkatësisht me çelësat dhe dekodimin e tyre.
Të dhënat janë shumë të lehta për t'u lidhur, vargjet mund të ndahen sipas indekseve.
Le të krijojmë dhe shqyrtojmë një varg si një shembull testimi dhe të shohim si do të ndikojë në rezultatin e transaksionit.
Ne e përfunduam duke thënë se Alice nuk mund të nënshkruante një transaksion Transfer, pasi kjo mundësi ishte bllokuar në @verifier për këtë lloj transaksioni.
Le të ushtrojmë me vargjet dhe pastaj ta lejojmë këtë.
RIDE Strings
Transaksioni është përsëri i mundur, ne dimë si të punojmë me vargjet.

ïżŒ
Në përmbledhje, kemi gjithçka të nevojshme për të shkruar logjikë të komplikuar DAO dApp.
Transaksionet e të dhënave
Transaksionet e të dhënave:
âMadhĂ«sia maksimale pĂ«r njĂ« çelĂ«s Ă«shtĂ« 100 karaktere, dhe njĂ« çelĂ«s mund tĂ« pĂ«rmbajĂ« pikĂ«kodet Unicode tĂ« rastit, duke pĂ«rfshirĂ« hapĂ«sirat dhe simbolet e tjera jo-printuese. Vlerat e vargjeve kanĂ« njĂ« kufi prej 32,768 byte dhe numri maksimal i hyrjeve tĂ« mundshme nĂ« transaksionet e tĂ« dhĂ«nave Ă«shtĂ« 100. NĂ« pĂ«rgjithĂ«si, madhĂ«sia maksimale e njĂ« transaksioni tĂ« dhĂ«nash Ă«shtĂ« rreth 140kbâââpĂ«r referencĂ«, pothuajse saktĂ«sisht gjatĂ«si e dramĂ«s sĂ« Shakespeare 'Romeo dhe Juliet'.
Krijojmë DAO me kushtet e mëposhtme:
PĂ«r tĂ« marrĂ« financim pĂ«r njĂ« startup, duke thirrur getFunds() nevojitet mbĂ«shtetje nga tĂ« paktĂ«n 2 pjesĂ«marrĂ«s â investitorĂ« DAO. Shfaqni mund tĂ« jetĂ« saktĂ«sisht aq sa u shpreh nĂ« sumĂ« nĂ« votim pronarĂ«t e DAO.
Le të krijojmë 3 lloje çelësh dhe të shtojmë logjikë për punën me bilancet në 2 funksione të reja, vote dhe getFunds:
xxâŠxx_ia = investitorĂ«t, bilanci i disponueshĂ«m (vote, deposit, withdrawal)
xxâŠxx_sv = startupet, numri i votave (vote, getFunds)
xxâŠxx_sf = startupet, numri i votave (vote, getFunds)
xxâŠxx = adresa publike (35 karaktere)
Vëreni se në Vote na duhej të përditësonim disa fusha menjëherë:
WriteSet([DataEntry(key1, value1), DataEntry(key2, value2)]),WriteSet na lejon të bëjmë disa regjistrime në kuadër të një invokeScript transaksioni.
Kështu duket në depozitë të dhënash DAO dApp, pas ia-depozitave:

Funksioni i depozitës na u ndryshua pak:

Tani po arrijmĂ« momentin mĂ« tĂ« rĂ«ndĂ«sishĂ«m nĂ« aktivitetin e DAO â votimi pĂ«r projektet pĂ«r financim.
Bob voton për projektin Neli me 500000 wavelets:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
Në depozitën e dhënave ne shohim të gjithë regjistrimet e nevojshme për adresën Neli:

Cooper gjithashtu votoi për projektin Neli.

Le të shohim kodin e funksionit getFunds. Neli duhet të mbledhë të paktën 2 vota për të pasur mundësi të tërheqë fonde nga DAO.

Neli planifikon të tërheqë gjysmën e shumës së besuar:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))
Ajo e arrin këtë, që do të thotë që DAO funksionon!
Ne shqyrtuam procesin e krijimit të DAO në gjuhën RIDE4DAPPS.
Në pjesët në vazhdim do të merremi më në detaje me refaktorizimin e kodit dhe testimin e rasteve.
Versioni i plotë i kodit në
# In this example multiple accounts can deposit their funds to DAO and safely take them back, no one can interfere with this.
# DAO participants can also vote for particular addresses and let them withdraw invested funds then quorum has reached.
# An inner state is maintained as mapping `address=>waves`.
# https://medium.com/waves-lab/waves-announces-funding-for-ride-for-dapps-developers-f724095fdbe1
# You can try this contract by following commands in the IDE (ide.wavesplatform.com)
# Run commands as listed below
# From account #0:
# deploy()
# From account #1: deposit funds
# broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"deposit",args:[]}, payment: [{amount: 100000000, asset:null }]}))
# From account #2: deposit funds
# broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"deposit",args:[]}, payment: [{amount: 100000000, asset:null }]}))
# From account #1: vote for startup
# broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
# From account #2: vote for startup
# broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
# From account #3: get invested funds
# broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))
{-# STDLIB_VERSION 3 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}
@Callable(i)
func deposit() = {
let pmt = extract(i.payment)
if (isDefined(pmt.assetId)) then throw("can hodl waves only at the moment")
else {
let currentKey = toBase58String(i.caller.bytes)
let xxxInvestorBalance = currentKey + "_" + "ib"
let currentAmount = match getInteger(this, xxxInvestorBalance) {
case a:Int => a
case _ => 0
}
let newAmount = currentAmount + pmt.amount
WriteSet([DataEntry(xxxInvestorBalance, newAmount)])
}
}
@Callable(i)
func withdraw(amount: Int) = {
let currentKey = toBase58String(i.caller.bytes)
let xxxInvestorBalance = currentKey + "_" + "ib"
let currentAmount = match getInteger(this, xxxInvestorBalance) {
case a:Int => a
case _ => 0
}
let newAmount = currentAmount - amount
if (amount < 0)
then throw("Can't withdraw negative amount")
else if (newAmount < 0)
then throw("Not enough balance")
else ScriptResult(
WriteSet([DataEntry(xxxInvestorBalance, newAmount)]),
TransferSet([ScriptTransfer(i.caller, amount, unit)])
)
}
@Callable(i)
func getFunds(amount: Int) = {
let quorum = 2
let currentKey = toBase58String(i.caller.bytes)
let xxxStartupFund = currentKey + "_" + "sf"
let xxxStartupVotes = currentKey + "_" + "sv"
let currentAmount = match getInteger(this, xxxStartupFund) {
case a:Int => a
case _ => 0
}
let totalVotes = match getInteger(this, xxxStartupVotes) {
case a:Int => a
case _ => 0
}
let newAmount = currentAmount - amount
if (amount < 0)
then throw("Can't withdraw negative amount")
else if (newAmount < 0)
then throw("Not enough balance")
else if (totalVotes < quorum)
then throw("Not enough votes. At least 2 votes required!")
else ScriptResult(
WriteSet([
DataEntry(xxxStartupFund, newAmount)
]),
TransferSet([ScriptTransfer(i.caller, amount, unit)])
)
}
@Callable(i)
func vote(amount: Int, address: String) = {
let currentKey = toBase58String(i.caller.bytes)
let xxxInvestorBalance = currentKey + "_" + "ib"
let xxxStartupFund = address + "_" + "sf"
let xxxStartupVotes = address + "_" + "sv"
let currentAmount = match getInteger(this, xxxInvestorBalance) {
case a:Int => a
case _ => 0
}
let currentVotes = match getInteger(this, xxxStartupVotes) {
case a:Int => a
case _ => 0
}
let currentFund = match getInteger(this, xxxStartupFund) {
case a:Int => a
case _ => 0
}
if (amount <= 0)
then throw("Can't withdraw negative amount")
else if (amount > currentAmount)
then throw("Not enough balance")
else ScriptResult(
WriteSet([
DataEntry(xxxInvestorBalance, currentAmount - amount),
DataEntry(xxxStartupVotes, currentVotes + 1),
DataEntry(xxxStartupFund, currentFund + amount)
]),
TransferSet([ScriptTransfer(i.caller, amount, unit)])
)
}
@Verifier(tx)
func verify() = {
match tx {
case t: TransferTransaction =>false
case _ => true
}
}
Burimi: habr.com
