Giriş
Pekala sevgili kodlama arkadaşım! Programlamadaki uzun yıllara dayanan deneyimimi ve biraz mizahımı kullanarak bu blockchain macerasında size rehberlik etmeme izin verin.
Bitcoin gibi dijital para birimleri ve birden fazla sektördeki çeşitli merkezi olmayan uygulamalar (DApp’ler) gibi çığır açan modern gelişmeler, blockchain teknolojisinden önemli ölçüde etkilenmektedir. Temel olarak bir blockchain, çok sayıda cihazdaki işlemleri kaydeden ve verilerin günlüğe kaydedildikten sonra değiştirilememesini sağlayan kolektif bir veritabanını temsil eder. Her işlem veya “blok” kendisinden önceki işlemle bağlantılı olup kesintisiz bir dizi oluşturur, dolayısıyla “blok zinciri” terimi kullanılır. Bu yapı, birçok uygulama için hayati önem taşıyan verilerin şeffaflığını, güvenliğini ve değişmezliğini garanti eder.
Blockchain’de JavaScript
JavaScript, özellikle blockchain çözümleri oluşturmak için yararlı olan, çok yönlü ve tanınmış bir programlama dili olarak öne çıkıyor. Geniş ekosistemi ve güçlü topluluk desteği, çeşitli avantajlar sunarak blockchain uygulamaları geliştirmeyi kolaylaştırır:
- Geniş Benimsenme: Javascript, web geliştirme için kullanılan temel dil olduğundan, web uygulamaları ile blockchain ortamında uygulamaya sahip olması çok açıktır.
- Eşzamansız İşleme: JavaScript’in Node.js tarafından sağlanan eşzamansız yetenekleri, bir blockchain ortamında birden fazla işlemin ve etkileşimin yönetilmesi için idealdir.
- Zengin Ekosistem: JavaScript ekosistemindeki, sunucu tarafı geliştirme için Node.js ve API’ler için Express.js gibi araçlar ve kitaplıklar, blockchain uygulama geliştirmeyi kolaylaştırır.
Kitle
Yıllar süren tecrübeye sahip deneyimli bir JavaScript geliştiricisi olarak, bu makaleyi becerilerini geliştirmek ve blockchain teknolojisinin büyüleyici dünyasına dalmak isteyen herkese tüm kalbimle tavsiye edebilirim. Bu kılavuz, geliştirme ortamınızı kurma, karmaşık kavramları anlaşılır temellere ayırma, temel bir blockchain uygulaması oluşturmanıza yardımcı olma ve sonuçta onu kullanıcı dostu bir API aracılığıyla kullanıma sunma sürecinde size yol gösterecektir. İster öğrenmeye hevesli olun, ister geliştirici yayınınıza yeni bir konu eklemek isteyin, bu makale yolculuğunuz için paha biçilemez bir kaynaktır.
Bölüm 1: Geliştirme Ortamını Kurma
Node.js’yi yükleme
- Node.js’yi resmi web sitesinden sisteminize indirin ve tüm işletim sistemleri için en iyisi önerildiği ve kararlılığı koruduğu için LTS (Uzun Süreli Destek) sürümünü tercih edin.
- İşletim sisteminize özel kurulum talimatlarını izleyin. Kurulum, proje bağımlılıklarını yönetmek için gerekli olan npm’yi (Düğüm Paket Yöneticisi) içerir.
- Bash’ta aşağıdaki komutları çalıştırarak kurulumun düzgün yapılıp yapılmadığını doğrulayın:
- düğüm -v
- npm -v
Verilen komutları yürüttükten sonra, kurulum işleminin başarılı olduğunu varsayarak, kurulu paketlerin ilgili versiyonlarını sisteminizde bulmalısınız.
IDE seçme
Programlama diliniz olarak JavaScript’i seçen Visual Studio Code (VSCode), tüm geliştirme gereksinimlerinizi karşılamanız için mükemmel bir yardımcıdır. Güçlü yetenekleri ve uyarlanabilir ortamı, onu JavaScript geliştirme için mükemmel bir seçim haline getirir.
- Visual Studio Kodu:
- VsCode’u resmi siteden indirin
- Uzantıları aşağıdaki gibi yükleyin:
- ESLint: JavaScript kodundaki sorunları tanımlamak ve düzeltmek için.
- Daha güzel: Tutarlı kod biçimlendirmesi için.
- Chrome için Hata Ayıklayıcı: Google Chrome’da çalışan JavaScript kodunda hata ayıklamak için.
- Node.js: Node.js’nin hata ayıklama yetenekleri için.
Gerekli Kitaplıkları Yükleme
JavaScript kitaplıklarının yönetimi npm (Düğüm Paket Yöneticisi) aracılığıyla yapılır. Projenizi başlatmak ve gerekli paketleri kurmak için aşağıdaki komutu kullanın:
npm init -y npm install express gövde ayrıştırıcı kriptosu //express düğüm çerçevesidir |
Bölüm 2: JavaScript ile Blockchain Kavramlarını Anlamak
JavaScript’te Blockchain Temelleri
Bir blockchain aşağıdakileri içeren bloklardan oluşur:
- Dizin: Bloğun zincirdeki konumu.
- Zaman damgası: Bloğun oluşturulduğu tarih ve saat.
- Veri: Blokta saklanan işlem verileri veya diğer bilgiler.
- Önceki Hash: Zincirdeki önceki bloğun hash’i, blokları birbirine bağlar.
- Hash: İçeriğin hashlenmesiyle oluşturulan, blok için benzersiz tanımlayıcı.
const crypto = require(‘crypto’); class Block { calculateHash { |
Merkezileşmenin, değişmezliğin ve fikir birliği mekanizmalarının önemi:
Merkeziyetsizlik:
Blockchain sistemlerinde, veri depolama ve işlem doğrulama için merkezi bir otoriteye güvenmek yerine sorumluluk, katılan tüm düğümler arasında dağıtılır. Bu, her düğümün defterin kendi kaydını (veya kopyasını) tutması ve tek bir kontrol noktasının neden olduğu olası sorunları ortadan kaldırması anlamına gelir.
Şeffaflık:
Ethereum‘u keşfeden bir araştırmacı olarak, ağdaki her düğümün ve katılımcının deftere erişebildiğini ve bu sayede tüm sistem genelinde değişmez şeffaflığın sağlandığını güvenle söyleyebilirim. Ethereum’daki işlemler, blockchain gezgininde herkesin görebileceği şekilde halka açık olarak görüntülenir ve katılan herkes için açık ve şeffaf bir ortam sağlanır.
Değişmezlik:
Bir işlemi tamamlamadan önce iyice düşünmek çok önemlidir, çünkü değişiklik veya geri alma genellikle olaydan sonra imkansızdır. Bu özellik, dolandırıcılık ve mükerrer işlemleri önlemek açısından değerlidir.
Uzlaşı Mekanizması:
Bir ağda, fikir birliği mekanizmaları, düğümlerin dağıtılmış defterin mevcut durumuna toplu olarak karar vermesi için kılavuz görevi görür. Bu mekanizmalar işlemlerin doğrulanması ve kimlik doğrulamasında etkilidir. Dağıtılmış Defter Teknolojisine (DLT) katılan tüm düğümlerin defterin durumu konusunda hemfikir olduğunu garanti ederler.
Blockchain Uygulamasının Bileşenleri
JavaScript’teki blok yapısı:
const crypto = require(‘crypto’); class Block { calculateHash { mineBlock(difficulty) { |
JavaScript kullanarak işlem oluşturma ve doğrulama:
Bir blok zincirde her işlem, değerdeki bir değişikliği, bir anlaşmanın uygulanmasını veya blok zincirinin genel durumundaki herhangi bir değişikliği temsil eden temel bir veri birimi olarak hizmet eder. Sistem bu işlemleri bloklar halinde toplar ve daha sonra bunları blok zincirine ekler.
İşlemin Ayrıntıları:
- Gönderen: Kimin gönderdiğinin genel anahtarı veya özel kimliği.
- Alıcı: İşlemi alan şanslı kişinin genel anahtarı veya özel kimliği.
- Tutar: İster para ister bilgi olsun, ortalıkta dolaşan şeyler.
- Zaman Damgası: Bu şeyi göndermeye karar verdiklerinde.
- Orijinallik Kanıtı/İmza: Anlaşmanın yasal olduğunu ve tahrif edilmediğini gösteren bazı süper gizli kod öğeleri. Bunu gönderen kişi, anlaşmayı imzalamak için kendi gizli anahtarını kullanır ve diğer herkes, ortak anahtarla bunun gerçek olup olmadığını kontrol edebilir.
İşleme ilişkin kod pasajı:
sınıf İşlem { yapıcı(fromAddress, toAddress, tutar) { this.fromAddress = fromAddress; this.toAddress = toAddress; bu.tutar = tutar; this.timestamp = new Date.toISOString; calculateHash { signTransaction(signingKey) { const hashTx = this.calculateHash; if (!this.signature || this.signature.length === 0) { const publicKey = ec.keyFromPublic(this.fromAddress, ‘hex’); |
Bir işlemin doğrulanması, imzalayanın meşru olduğunu ve yeterli paraya sahip olduğunu doğrulayarak işlemin gerçekliğini garanti altına alır. Bu süreç genellikle dijital imzanın bütünlüğünün kontrol edilmesini ve gönderenin hesap bakiyesinin işlem değerine eşit veya bu değeri aştığının doğrulanmasını gerektirir.
sınıf Blockchain { yapıcı { this.chain = [this.createGenesisBlock]; this.pendingTransactions = []; this.miningReward = 100; createGenesisBlock { getLatestBlock { minePendingTransactions(miningRewardAddress) { console.log(‘Blok başarıyla çıkarıldı !’); if (!transaction.isValid) { this.pendingTransactions.push(transaction); getBalanceOfAddress(address) { for (this.chain’in const bloğu) { if (trans.toAddress === adres) { < br/> bakiye += işlem tutarı; dönüş bakiyesi; isChainValid { if (currentBlock.hash !== currentBlock.calculateHash) { if (currentBlock.preciousHash !== öncekiBlock.hash) { doğruyu döndür; |
JavaScript ile uyumlu fikir birliği algoritmalarına genel bakış:
İş Kanıtı (PoW):
Daha basit bir ifadeyle Proof of Work (genellikle madencilik olarak anılır), işlemleri doğrulamak ve bir blok zincirinde yeni bloklar oluşturmak için kullanılan bir yöntemdir. Kullanıcılar karmaşık matematik problemlerini veya ‘kriptografik bulmacaları’ çözmek için yarışırlar. Bulmacayı ilk çözen, zincire bir sonraki bloğu ekleyecek. Bu süreç, blok zincirinin bütünlüğünü ve güvenliğini sağlayan karma algoritmalar kullanılarak güvence altına alınır.
Daha basit bir ifadeyle, İş Kanıtı’nı (PoW) hayata geçirmek söz konusu olduğunda, bu amaca yönelik araçlar, Bitcoin Core’u içeren Bitcoin Development Suite içerisinde sunulmaktadır.
Stake Kanıtı (PoS):
Daha basit bir ifadeyle Proof of Stake, doğrulayıcıları yalnızca teminat olarak tuttukları koin miktarına göre değil, aynı zamanda paraların yaşı ve bir miktar rastgelelik gibi faktörleri de dikkate alarak seçer. Seçim süreci, daha uzun süredir coin tutan ve daha yüksek hisseye sahip doğrulayıcıları desteklerken aynı zamanda düşük hash değeri ve yüksek toplam stake miktarıyla adaleti de sağlıyor. Bu tercih edilen doğrulayıcılar daha sonra blok zincirine yeni bir blok eklemekle görevlendirilir.
Geliştirici Uygulaması: PoS için araçlar ve kütüphaneler Ethereum 2.0 SDK tarafından sağlanmaktadır
Yetkilendirilmiş Hisse Kanıtı (DPoS):
Daha basit bir ifadeyle bu sistem, işlemleri onaylamak ve yeni bloklar oluşturmak için demokratik bir yaklaşım kullanıyor. Bunu, katılımcılar arasında (‘delegeler’ olarak anılır) oylamalara izin vererek, işlemleri doğrulamak ve bir blok zincirinde yeni bloklar oluşturmak için yapar.
Geliştirici Uygulaması: EOSIO SDK, DPoS için araçlar ve kitaplıklar sağlar.
Bölüm 3: JavaScript ile Basit Bir Blockchain Oluşturmak
Bu derste, bloklar gibi temel sınıfların oluşturulmasını, bunların niteliklerini tanımlamayı ve bu bloklar ile parametrelerinin birbirine nasıl bağlandığını anlayarak blockchain mimarisini derinlemesine inceleyeceğiz.
Blok Sınıfını Oluşturma
Blockchain, adının temsil ettiği şekliyle bloklardan ve her blok sınıfının aşağıdaki gibi temel özelliklerinden oluşur:
- Endeks: Bloğun blockchain içindeki konumu için sayısal bir tanımlayıcı.
- Zaman Damgası: Bloğun oluşturulduğu zaman.
- Veri: Blokta saklanan veriler veya işlemler. Bu, işlem ayrıntıları, kullanıcı verileri vb. bilgileri içerebilir.
- Önceki Hash: Zincirdeki bir önceki bloğun sürekliliğini ve güvenliğini sağlayan hash’i.
- Hash: Bloğun içeriğinin hashlenmesiyle oluşturulan, blok için benzersiz bir tanımlayıcı.
- Nonce: İş Kanıtı algoritması için kullanılan ve geçerli bir karma bulunana kadar ayarlanan bir sayı.
JavaScript sözdizimini kullanarak bloğun karmasını hesaplamak için yöntemler uygulayın:
- createGenesisBlock: Blockchain’de, oluşum bloğu olarak bilinen ilk bloğu oluşturur.
- getLatestBlock: Blok zincirindeki en son bloğu alır.
- adBlock: Madenciliğin ardından blok zincirine yeni bir blok ekler.
- isChainValid: Her bloğun karma eşleşmelerini ve önceki karmaların tutarlı olmasını sağlayarak blok zincirinin bütünlüğünü doğrular.
Blockchain Sınıfını Oluşturma
Zinciri yönetmek ve yeni bloklar eklemek için yöntemler uygulamak için bir Blockchain sınıfı tanımlayın:
sınıf Blockchain { yapıcı { this.chain = [this.createGenesisBlock]; bu.zorluk = 4; // Madencilik için zorluk düzeyi yeni Blok’u döndür(0, “01/01/2024”, “Genesis Block”, “0”); // Zincirdeki en son bloğu alma yöntemi < br/>getLatestBlock { // Zincire madencilik yaptıktan sonra yeni bir blok ekleme yöntemi // Blok zincirinin bütünlüğünü doğrulama yöntemi // Şunun olup olmadığını kontrol edin: geçerli bloğun karması doğrudur |
Bölüm 4: JavaScript’te Uzlaşı Mekanizmalarını Uygulama
İş Kanıtı
Daha basit bir ifadeyle Proof of Work (genellikle madencilik olarak adlandırılır), ağ katılımcılarının veya madencilerin kriptografik kodlu bulmacalara benzeyen karmaşık matematik problemlerini çözmek için yarıştığı bir sistemdir. Bulmacayı ilk çözen madenci, blockchain olarak bilinen veri zincirine bir sonraki bloğu ekler ve bir ödül alır. Bu süreç, blok zincirini güvende tutmak için karma işleminin kullanılmasını içerir. Bu bulmacaların karmaşıklığı, blok zincirinin güvenliğinin korunmasına yardımcı olur ve yeni blokların zincire ne kadar hızlı eklendiğini düzenler.
Block sınıfında bir ‘mineBlock’ fonksiyonu oluşturarak Proof of Work konseptini dahil edelim. Bu işlev, bloğun kodlanmış karma değeri belirli bir karmaşıklık standardını karşılayana kadar (örneğin, karma belirli sayıda sıfırla başlamalıdır) nonce’ı sürekli olarak ayarlayacaktır.
Kod Parçacığı:
sınıf Blok { yapıcı(dizin, zaman damgası, veri, öncekiHash = ”) { this.index = dizin; this.timestamp = timestamp; this.data = veri; this.öncekiHash = öncekiHash; this.hash = this.calculateHash; bu.anlık = 0; } // SHA-256’yı kullanarak bloğun karmasını hesaplayın // İş Kanıtını Uygulama |
Yeni bloklar eklemeden önce kanıtı doğrulamak için Blockchain sınıfını güncelleyin.
sınıf Blockchain { yapıcı { this.chain = [this.createGenesisBlock]; bu.zorluk = 4; // Genesis bloğunu oluşturun yeni Blok’u döndür(0, “01/01/2024”, “Genesis Block”, “0”); // Zincirdeki en son bloğu alın // Zincire yeni bir blok ekleyin // Blok zincirinin geçerli olup olmadığını kontrol edin if (currentBlock.preciousHash !== öncekiBlock.hash) { |
Bölüm 5: JavaScript ile Basit Blockchain API’si Oluşturma
Bir blockchain geliştirmek yalnızca ilk adımdır; aynı zamanda günlük kullanım için de pratik olmalıdır. Bu hedefe ulaşmak için kolay etkileşime olanak tanıyan basit bir API (Uygulama Programlama Arayüzü) gibi kullanıcı dostu bir arayüz tasarlamalıyız.
API Ortamını Kurma
Etkili bir API oluşturmak için öncelikle geliştirilmesi için gerekli tüm araçları ve çerçeveleri yükleyerek çalışma alanını hazırlamanız çok önemlidir.
- Düğümü ve npm’yi yükleyin
- Projenizi şu komutla başlatın: npm init -y
- Express’i yükleyin: npm install express -save (Express, API’lerin daha hızlı oluşturulmasına yardımcı olan node js çerçevesidir)
- Gelen isteği işlemek için Gövde ayrıştırıcısını kurun: npm install body-parser -save
API’yi oluşturma
Kurulumunuzu hazırladıktan sonra Uygulama Programlama Arayüzünü (API) oluşturmaya devam edelim. Bu arayüz, kullanıcıların blockchain ile iletişim kurmasına, zincirin mevcut durumunu gözlemlemesine ve hatta ona yeni bloklar eklemesine olanak tanıyacak.
Sunucuyu Express ile oluşturun:
const express = require(‘express’); const bodyParser = require(‘body-parser’); const Blockchain = require(‘./blockchain’); // Blockchain sınıfını içe aktarın const app = express; let demoBlockchain = yeni Blockchain; // Yeni bir Blockchain örneğini başlat |
API uç noktalarını tanımlama
app.get(‘/blocks’, (req, res) => { //blok zincirini almak için uç nokta res.json(demoBlockchain.chain);}); //bu, yeni bir blok oluşturmak için son noktadır app.post(‘/mine’, ( req, res) => { |
Sunucuyu başlatın
app.listen(3000, => { console.log(‘Blockchain API’si 3000 numaralı bağlantı noktasında çalışıyor’); }) ; düğüm sunucusu.js |
Bölüm 6: Uygulamayı Çalıştırma ve Test Etme
Blockchain’inizin sorunsuz çalışmasını ve beklediğiniz sonuçları sunmasını sağlamak için bu aşamanın önemini yeterince vurgulayamam. Yıllarca çeşitli blockchain teknolojileriyle çalışmış biri olarak, bu kritik adımın ihmal edilmesi nedeniyle sayısız projenin başarısız olduğunu gördüm. Aynı hatayı yapmayın; blok zincirinizi hayata geçirmeden önce iyice test etmeye ve geliştirmeye zaman ayırın. Güven bana; kullanıcılarınız bunun için size teşekkür edecek!
Uygulamayı Çalıştırma
- Sunucuyu başlatın: Proje dizininize gidin ve ardından hedefi çalıştırın: node server.js
- Sunucu Onayı Alın: 3000 numaralı bağlantı noktasında çalışan Blockchain API’si
- Uygulamaya Erişim: Uygulamanız artık yerel olarak http://localhost:3000 üzerinde çalışıyor ve HTTP isteklerini kabul etmeye hazır hale geliyor
Postacı ile Test Etme
Bir kripto yatırımcısı olarak blockchain API’lerimin en iyi şekilde çalıştığından emin olmak için genellikle Postman gibi araçlara güveniyorum. Postman ile kolayca HTTP istekleri gönderebiliyor ve bunların döndürdüğü yanıtları analiz edebiliyorum. Bu araç, API’min performansını test etmek ve doğrulamak, yatırımlarımı güvenli ve verimli tutmak açısından çok değerli.
- Postacıyı Yükle
- Blockchain Uç Noktasını Test Etme
- Madencilik uç noktasını test edin
- Blockchain’i doğrulayın
(Adım 1)node server.js 3000 numaralı bağlantı noktasında çalışan Blockchain API’si //http://localhost: 3000/blok (Adım 2)[ ] (Adım 3){ (4. Adım){ (5. Adım)[ { |
curl http://localhost:3000/blocks //Blockchain’i görüntüleyin [ { “dizin”: 0, “zaman damgası”: 1636568887994, “veri”: “Genesis Block”, “önceki Hash”: “0”, “karma”: “81f1a4ab4d484c64f1b4c524b1d8f2fef8f2bca7853d44682e12022fb2d803b9” ] //Yeni bir blokcurl madenciliği -X POST -H “Content-Type: application /json” -d ‘{“veri”: {“miktar”: 100, “gönderen”: “John Doe”, “alıcı”: “Jane Smith”}}’ http://localhost:3000/mine //blockcurl’u doğrulayın http://localhost:3000/blocks [ ] |
Bölüm 7: JavaScript ile Blockchain Uygulaması Oluşturmanın Canlı Örneği
Adım Adım Yürütme
- 1. Adım: JavaScript sözdizimini kullanarak gerekli niteliklere sahip Block sınıfını oluşturun.
sınıf Blok { yapıcı(dizin, zaman damgası, veri, öncekiHash = ”) { this.index = dizin; this.timestamp = timestamp; this.data = veri; this.öncekiHash = öncekiHash; this.hash = this.calculateHash; bu.anlık = 0; |
- 2. Adım: accountHash yöntemini uygulayın.
calculateHash { return crypto.createHash(‘sha256’) .update(this.index + this.öncekiHash + this.timestamp + JSON.stringify(this.data) + this.nonce) .digest(‘hex’); |
- 3. Adım: Blockchain sınıfını tanımlayın ve onu bir oluşum bloğuyla başlatın.
sınıf Blockchain { yapıcı { this.chain = [this.createGenesisBlock]; |
- 4. Adım: JavaScript kullanarak yeni bloklar eklemek ve en son bloğu almak için yöntemler uygulayın.
getLatestBlock { return this.chain[this.chain.length – 1]; addBlock(newBlock) { |
- 5. Adım: Block sınıfına Proof of Work işlevini ekleyin ve Blockchain sınıfını güncelleyin.
mineBlock(zorluk) { while (this.hash.substring(0, zorluk) !== Array(zorluk + 1).join(“0”)) { bu.nonce++; this.hash = this.calculateHash; |
- 6. Adım: API ortamını, istekleri Express kullanarak işleyecek şekilde ayarlayın.
npm init -y npm install express -save //Projeyi ve dizini ayarlama const express = require(‘express’); //Ekspres sunucuyu ayarlamaconst bodyParser = require(‘body-parser’); const app = express;app.use(bodyParser.json); const demoBlockchain = yeni Blockchain; app.post(‘/mine’, (req, res) => { //yeni bir blok oluşturma const newBlock = new Block( düğüm sunucusu.js |
- 7. Adım: Yeni bir blok madenciliği yaparak ve Postman veya curl kullanarak blok zincirini doğrulayarak uygulamayı test edin.
Postacıda isteği gönderin: İsteği http://localhost:3000/blocks adresine GET. { < br/>“veri”: { “miktar”: 10, “gönderen”: “Alice”, “alıcı”: “Bob” curl:curl’da |
Yukarıdaki adımları kısaca özetleyelim
Blockchain uygulamanızı hayata geçirmek için süreci adım adım inceleyelim:
- Blockchain’inizin temel yapısını oluşturmak için Block ve Blockchain sınıflarını tanımlayarak başlayın.
- mineBlock yöntemini Block sınıfına ekleyerek Proof of Work’ü dahil edin ve her bloğun zincire eklenmeden önce gerekli zorluğu karşıladığından emin olun.
- Blockchain’inizle etkileşim kurmanıza olanak tanıyan, zinciri görüntüleme ve yeni bloklar ekleme gibi işlemleri mümkün kılan Express’i kullanarak bir API kurun.
- Blok madenciliği yapmaktan blockchain verilerini almaya kadar her şeyin beklendiği gibi çalıştığını doğrulamak için uygulamanızı Postman veya curl ile yürütün ve test edin.
Mutlu Kodlama!!
- Charmed’dan Finola Hughes ‘Savaşçı’ Shannen Doherty’yi Hatırlıyor: ‘Savaştı’
- Kamala Harris, Kripto Tepkisinin Ortasında Ripple CEO’sunda Müttefik Buldu
2024-08-14 21:30