Lo sviluppatore Christophe Verdo parla del corso online ‘’, che ha recentemente completato.

Parlami un po' di te. Cosa ti ha attirato in questo corso?
Mi occupo di sviluppo web da circa 15 anni, principalmente come freelance.
Lavorando a un'applicazione web per la registrazione a lungo termine per paesi in via di sviluppo su commissione di un gruppo bancario, mi sono imbattuto nella sfida di integrarne la certificazione tramite blockchain. All'epoca non sapevo molto sulla certificazione blockchain, anche se mi interessavo già di tecnologie crittografiche, principalmente come investitore.
Alla fine questa funzionalità non è stata realizzata, ma riflettendo sul fatto che organizzazioni e banche sono interessate a una soluzione di questo tipo per le loro applicazioni, ho iniziato a studiare la questione e ho avviato il progetto .
Ho sviluppato la sua versione beta, già disponibile nella rete principale. All'epoca non esisteva il linguaggio di programmazione Waves Ride, e ho fatto tutto nel modo più semplice, utilizzando transazioni di trasferimento con JSON incorporato. Ma l'obiettivo principale era aggiungere funzionalità più avanzate dopo il lancio di Ride. E questa è la ragione principale per cui mi sono unito al corso: la fase successiva dello sviluppo del progetto prevedeva la creazione di un'app decentralizzata (dApp).
Quali aspetti del corso ti sono sembrati i più semplici e quali i più complessi?
La parte più semplice è stata che avevamo abbastanza tempo per tutti i compiti. Lo scopo del corso è imparare qualcosa, non competere tra di noi. Le spiegazioni erano molto accessibili e le illustrazioni semplici ma esaustive. Questo ha aiutato a visualizzare e comprendere diversi argomenti.
Durante l'esecuzione dei compiti siamo stati incoraggiati a pensare in modo indipendente e a studiare qualche cosa da soli. Questo è il modo migliore per apprendere e comprendere le idee trattate nelle lezioni.
In diverse occasioni non ho completamente compreso la parte teorica fino a quando non ho iniziato a scrivere il codice per completare l'incarico. Non ci era permesso fare ‘copy/paste’, bisognava scrivere tutto il codice da soli, e questo ha aiutato a capire meglio tutto.
La cosa più difficile è stata che le domande dell'incarico con risposte multiple non erano sempre chiare. Il mio inglese non è perfetto, e le domande erano scritte da qualcuno che non è madrelingua, quindi a volte c'erano malintesi.
Forse la parte del corso dedicata agli oracoli e agli NFT potrebbe essere più dettagliata. Ma, in ogni caso, l'obiettivo principale del corso è quello di suscitare l'interesse dei programmatori. Poi, per comprendere appieno tutti gli aspetti, sarà necessario investire del tempo per sperimentare e praticare.
Parlateci di più della soluzione su cui avete lavorato durante tutto il corso – 'Coupon Bazaar'? Possiamo anche vedere degli esempi di codice?
Sì, abbiamo lavorato su ‘Coupon Bazaar’, un marketplace dove le persone possono comprare e vendere coupon che permettono di acquistare beni e servizi a prezzi più bassi. Ogni coupon è rappresentato come un asset digitale, che implica uno sconto speciale da parte del fornitore.

Era necessario sviluppare diversi componenti dell'app. In primo luogo, dovevamo creare un sistema per la registrazione dei fornitori e la gestione dei coupon. Poi era necessaria una funzione di verifica e la possibilità per gli utenti di cercare i coupon.

Durante il corso abbiamo anche aggiunto alcune nuove funzionalità, tra cui un sistema di votazione e una funzione che consente di verificare e mettere in blacklist i fornitori.
Innanzitutto abbiamo esaminato le differenze tra smart asset, smart account e dApp account, e come funzionano le funzioni di verifica. Le funzioni di verifica consentono di modificare il comportamento dell'account definito per impostazione predefinita. Di default, controllano le firme delle transazioni, ma la funzione di verifica consente di stabilire altre ‘regole’.
{-# STDLIB_VERSION 3 #-}
{-# CONTENT_TYPE DAPP #-}
{-# SCRIPT_TYPE ACCOUNT #-}
letownerPublicKey = base58'H8ndsHjBha6oJBQQx33zqbP5wi8sQP7hwgjzWUv3q95M'
@Verifier(tx)
funcverify() = {
matchtx {
cases: SetScriptTransaction=>sigVerify(tx.bodyBytes, tx.proofs[0], ownerPublicKey)
cased: DataTransaction=>true
case_ =>false
}
}Abbiamo poi iniziato ad aggiungere coupon. Abbiamo utilizzato una delle funzioni più importanti del dApp, che permette di registrare nel blockchain dati di qualsiasi tipo sotto forma di coppie "chiave-valore" – una transazione di dati. L'abbiamo combinata con la nuova transazione, invokeScript, usata per richiamare la funzione del dApp dall'esterno del blockchain.
Il tipo di transazioni dati che abbiamo utilizzato durante il corso è l'aggiunta di coupon al marketplace:
letdatajson = {
"title": "t-shirt with , vote 1",
"coupon_price": 10000000,
"old_price": 1000000000,
"new_price": 100000000,
"address": "Universe",
"description": "Voglio che tu faccia l'amore, non la guerra, so che l'hai già sentito prima",
"image": "https://bit.ly/2EXTghg"
}
it('add item', asyncfunction(){
letts = invokeScript({
dApp: dappAddress,
call:{
function:"addItem",
args:[
{ type:"string", value: datajson.title },
{ type:"integer", value: datajson.coupon_price },
{ type:"string", value: JSON.stringify(datajson) }
]},
payment: []
}, accountSupplierSeed)
lettx = awaitbroadcast(ts)
awaitwaitForTx(tx.id)
})Per gestire questi dati con la funzione addItem e sviluppare la funzione di acquisto e altre opzioni, abbiamo utilizzato una funzione chiamata, che l'utente può chiamare dall'esterno della blockchain. Di conseguenza, può eseguire varie attività, come avviare un trasferimento di fondi, registrare o aggiornare dati nello storage dati dApp, ecc.
Ecco un esempio di funzione chiamabile, utilizzata nella funzione addItem:
@Callable(i)
func addItem(title: String, price: Int, data: String) = {
let supplierAddress = toBase58String(i.caller.bytes)
let item = getKeyItem(supplierAddress, title)
if( price <= 0) then throw("l'importo dell'acquisto non può essere inferiore al prezzo dell'articolo")
elseif( getValueItemSupplier(item) != NONE ) then throw("l'articolo esiste già")
else{
WriteSet([
DataEntry(getKeyItemSupplier(item), supplierAddress),
DataEntry(getKeyItemPrice(item), price),
DataEntry(getKeyItemData(item), data)
])
}
}In seguito, abbiamo sviluppato un sistema di voto che consente di votare per la promozione o la rimozione di specifici prodotti. Per evitare influenze esterne sul processo di voto, utilizza uno schema ‘Commit-Reveal’.
La fase 'commit' viene utilizzata per raccogliere voti crittografati usando una funzione hash e un 'sale'.
La fase 'reveal' viene utilizzata per raccogliere voti crittografati e confrontarne gli hash.
Ecco un esempio di funzione chiamata utilizzata qui:
@Callable(i)
funcvoteCommit(item: String, hash: String) = {
letuser = toBase58String(i.caller.bytes)
letcommits = getValueCommitsCount(item)
letstatus = getValueItemStatus(item)
if( commits >= VOTERS) thenthrow("numero massimo di votanti raggiunto")
elseif(getValueCommit(item, user) != NONE) thenthrow("l'utente ha già partecipato")
elseif(getKeyItemSupplier(item) == NONE) thenthrow("l'elemento non esiste")
elseif(status != NONE && status != VOTING) thenthrow("votazione non possibile")
else{
WriteSet([
DataEntry(getKeyCommit(item, user), hash),
DataEntry(getKeyCommitsCount(item), commits + 1),
DataEntry(getKeyItemStatus(item), if(commits == VOTERS) then REVEAL else VOTING)
])
}
}
>Cosa altro hai appreso dal corso?
Il corso ha incluso anche la tokenizzazione e i token non fungibili (NFT) – token che rappresentano qualcosa di unico e pertanto non intercambiabile.
L'ultima lezione era dedicata agli oracoli. Poiché la blockchain non può ricevere dati dal mondo esterno, abbiamo bisogno di oracoli per inviare questi dati.
Per il nostro marketplace, gli oracoli erano necessari per verificare e, se necessario, mettere in blacklist il fornitore che, ad esempio, non ha accettato il coupon venduto.
Ecco un esempio:
funcgetExtValueItemWhiteListStatus(item:String) = {
item +"_verifier_status"
}
letverifier = "3Mx9qgMyMhHt7WUZr6PsaXNfmydxMG7YMxv"
letVERIFIED = "verificato"
letBLACKLISTED = "blacklist"
@Callable(i)
funcsetstatus(supplier: String, status: String) = {
letaccount = toBase58String(i.caller.bytes)
if( account !=verifier ) thenthrow("solo l'oracolo verificatore può gestire la whitelist")
elseif( status !=VERIFIED && status !=BLACKLISTED) thenthrow("stato errato")
else{
WriteSet([
DataEntry(getExtValueItemWhiteListStatus(supplier), status)
])
}
}
Cosa è stato più utile per te?
La parte più utile è stata quella degli esercizi. Grazie a loro, il materiale delle lezioni diventava più chiaro e le nuove conoscenze venivano consolidate tramite prove ed errori. Anche il lavoro pratico con , e .
Come prevedi di utilizzare ciò che hai appreso nella pratica?
Sin dall'inizio, mi aspettavo che il corso potesse portare il mio progetto a un nuovo livello. L'idea era di scrivere ora il codice su RIDE. La versione attuale ha già le funzionalità di certificazione dei documenti, ma grazie a RIDE, potrà essere migliorata significativamente. La nuova versione sarà più flessibile e chiara, con più funzioni, inclusa la certificazione di email, accordi tra più parti, ecc.
Il corso ha suscitato molte riflessioni in me, e ho avuto molte nuove idee. Sono certo che i risultati si manifesteranno anche in futuro.
Fonte: habr.com
