
Баарына салам!
В бөлүгүндө биз dApp (борбордон ажыратылган тиркеме) кантип түзүүнү жана аны менен иштөөнү майда-чүйдөсүнө чейин карап чыктык .
Келгиле, азыр демонтаждалганын бир аз сынап көрөлү .
3-этап. dApp каттоо эсебин текшерүү

Алиса менен кандай көйгөйлөр дароо пайда болду? dapper Эсептин?
Биринчиден:
Boob жана Cooper кокусунан dApp дарегине акча жөнөтүшү мүмкүн ташуу транзакциялар жана ошондуктан аларга кайра кире албай калат.Экинчиден:
Биз Алисага Boob жана/же Купердин уруксатысыз акча каражаттарын алуусун эч кандай түрдө чектебейбиз. Анткени, текшерүүгө көңүл буруңуз, Алисадан бардык транзакциялар аткарылат.
Алисага тыюу салуу менен 2ни оңдойлу ташуу транзакциялар. Келгиле, оңдолгон скриптти колдонолу:


Биз dApp Алисадан жана анын кол тамгасынан тыйындарды алууга аракет кылып жатабыз. Биз ката алабыз:

Келгиле, алып салуу аркылуу чыгарууга аракет кылалы:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"withdraw",args:[{type:"integer", value: 1000000}]}, payment: []}))Сценарий иштейт жана биз 2-пунктту түшүндүк!
4-этап. Добуш берүү менен DAO түзүү
Тилекке каршы, RIDE тили коллекциялар (сөздүк сөздүктөр, итераторлор, редукторлор ж.б.) менен иштөө мүмкүнчүлүгүн азырынча камсыздай элек. Бирок, жалпак коллекциялар менен ар кандай операциялар үчүн ачкыч биз саптар менен иштөө системасын, ошого жараша ачкычтар жана алардын шифрлөө менен иштеп чыга алабыз.
саптарды бириктирүү абдан оңой;
Сыноо үчүн мисал катары сапты чогултуп, талдап көрөлү жана бул транзакциянын жыйынтыгына кандай таасир этээрин текшерип көрөлү.
Биз Элистин Transfer транзакциясына кол кое албаганына токтолдук, анткени бул жөндөм транзакциянын бул түрү үчүн @verifierде бөгөттөлгөн.
Келгиле, саптар менен машыгып, анан муну чечели.
RIDE Strings
Бүтүм кайра мүмкүн, биз саптар менен иштөөнү билебиз.


Жалпысынан алганда, биз татаал логиканы жазуу үчүн зарыл болгон нерселердин баары бар DAO dApp.
Маалымат транзакциялары
Маалымат транзакциялары:
“Ачкычтын максималдуу өлчөмү 100 символду түзөт жана ачкыч боштуктарды жана башка басып чыгарууга мүмкүн эмес символдорду камтыган ыктыярдуу Юникод кодунун чекиттерин камтышы мүмкүн. Саптык маанилердин чеги 32,768 100 байт жана берилиш транзакциясындагы мүмкүн болгон жазуулардын максималдуу саны 140. Жалпысынан, транзакциянын максималдуу көлөмү XNUMX кбдын тегерегинде — маалымдама үчүн, Шекспирдин "Ромео жана Джульетта" пьесасынын дээрлик так узундугу. '.
Биз төмөнкү шарттар менен DAO түзөбүз:
Стартап телефон чалып каржылоону алуу үчүн getFunds() кеминде 2 катышуучунун - DAO инвесторлорунун колдоосу талап кылынат. алып көрсөтүлгөн жалпысынан дал ошончолук мүмкүн болот добуш берүү DAO ээлери.
Келгиле, ачкычтардын 3 түрүн жасайлы жана добуш берүү жана getFunds 2 жаңы функциясында баланстар менен иштөө логикасын кошолу:
хх...хх_ia = инвесторлор, жеткиликтүү баланс (добуш берүү, депозиттик алуу, алуу)
хх...хх_sv = стартаптар, добуштардын саны (добуш берүү, getFunds)
хх...хх_sf = стартаптар, добуштардын саны (добуш берүү, getFunds)
xx…xx = коомдук дарек (35 белги)
Сураныч, добуш берүүдө биз бир эле учурда бир нече талааны жаңыртышыбыз керек экенин эске алыңыз:
WriteSet([DataEntry(key1, value1), DataEntry(key2, value2)]),WriteSet бизге бир эле учурда бир нече жазууларды жасоого мүмкүндүк берет invokeScript транзакциялар.
Бул Боб менен Купер толукталгандан кийин, DAO dApp ачкыч-нарк сактагычында ушундай көрүнөт ia- депозиттер:

Депозиттик функциябыз бир аз өзгөрдү:

Эми DAOнун ишиндеги эң маанилүү учур келди - добуш берүү каржылана турган долбоорлор үчүн.
Боб Нелинин 500000 XNUMX толкун долбоору үчүн добуш берет:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"vote",args:[{type:"integer", value: 500000}, {type:"string", value: "3MrXEKJr9nDLNyVZ1d12Mq4jjeUYwxNjMsH"}]}, payment: []}))
Маалыматтар дүкөнүндө биз Нелинин дареги үчүн бардык керектүү жазууларды көрөбүз:

Купер да Нели долбооруна добуш берди.

Келгиле, функциянын кодун карап көрөлү getFunds. Нели DAOдан акча ала алыш үчүн кеминде 2 добуш топтошу керек.

Нели ага ишенип берилген акчанын жарымын алмакчы:
broadcast(invokeScript({dappAddress: address(env.accounts[1]), call:{function:"getFunds",args:[{type:"integer", value: 500000}]}, payment: []}))
Ал ийгиликке жетет, башкача айтканда, DAO иштейт!
Биз тилде DAO түзүү процессин карап чыктык RIDE4DAPPS.
Кийинки бөлүктөрдө биз кодду рефакторингди жана кейс тестирлөөсүн тереңирээк карап чыгабыз.
Коддун толук версиясы
# 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
}
}
Source: www.habr.com
