Moving to Crypto Valley
Not many know this, but I've had my eyes set on Zug long before Ethereum registered its foundation there. The quiet town that is close enough to Zurich for a potential daily commute, yet still small enough to give you a genuine Swiss experience, was in my top 3 relocation candidates list since 2013.
So together with the growing Crypto scene there, it was the perfect storm of events that gave me the final push to move to Zug.Between Cloud and Crypto
In the summer of 2017, we at Cloudwith.me have introduced a new token to usher a new age of Cloud.
The plan is multi-faceted, and quite complex, but to focus on the current stage - The new Cloud Token is made to be the de facto currency to purchase Cloud Services.
Whether those are servers at Cloudwith.me (currently supporting Google Cloud, AWS, and Microsoft Azure), or Cloud products at other Cloud providers & merchants that will soon adopt the Cloud Token.
Due to this exciting turn of events, it has become more and more critical to keep up with the fastest changing tech landscape in the world - Crypto/Blockchain technology.Why Crypto Valley?
"If Satoshi Nakamoto were a trustee, we would've found him for you." - street advertisement in Zug
I often hear that a decentralized technology should have a decentralized ecosystem, I guess the physical world doesn't work that way.
For Crypto, there seem to be 3 main hubs: Zug, Hong Kong, and Singapore.
As I'm already living in Europe, speak German, and am not a Megacity person (HK & SG aren't technically Megacities, but they sure feel like ones), Zug seemed like the obvious choice.
Zug is also the home of The Ethereum Foundation, Crypto Valley Association, ShapeShift, Lisk, and thousands of other Crypto companies.
With a direct flight to every major city in Western Europe within 1-3 hours (not to mention the train connections), it's a prime location both from and to conferences/meetings.What's Next?
This move has been the slowest settling period I've had, perhaps with the exception of my initial move to Berlin. I keep trying to find a reason for this, and I think it has to do with the suburban lifestyle of Switzerland. I'm used to getting all my answers online. In fact, with enough research, one can have almost the same knowledge as a local, before moving to a capital city. This all falls apart when one moves to a smaller town. Local knowledge is just not out there in the Googleverse. The simplest questions such as "Who's the best Internet Provider?", or "How does waste disposal work?" change drastically even between communities.
The best solution for this is - joining local groups (some are even on Facebook), and be patient - you'll figure it out sooner or later.
After finally settling in, I feel like it's time to get to work!
I'm working on 2 key directions at the moment, as well as a potential 3rd one.Business Partnerships
The goal is to finalize an agreement with at least 2-3 cloud providers/merchants to accept Cloud Tokens.
We have had several talks with several niche cloud providers, but the complexity of Token transactions has been the biggest blocker here. Since we rely on the Ethereum blockchain, we are limited with the amount of simplification we can do on our end.
However, recent developments on MetaMask are inching closer and closer towards a sane way to pay with Ether & Tokens (almost PayPal-like). Seamless integration is a matter of months, if not weeks, so it's definitely a reason to stay positive.Technological Partnerships
As mentioned above, promoting seamless token transactions right from the browser is not only beneficial to our Cloud Token, it's beneficial to the entire Ethereum community. In fact I would go so far and say that MetaMask has the potential to lead to mass adoption of the Ethereum blockchain.
The priority here is contributing directly to MetaMask, as well building integrations/plugins for the extension.Bridging the gap
The 3rd potential direction is more of a trend that has been bothering me as of late.
I see a huge gap between potential contributors/investors and actual developers.
There are a lot of campaigns out there, talking about incredible ideas, but without technical knowledge investors are left guessing in the dark. I believe there is plenty of work to do on this front,
both on the technical side, as well as on the human side.
One last thing - I've made a few design changes, time for a refresh :)Posted in Crypto, TechnologyAdding Serverless to your Web Application
As you've probably heard, Serverless is the next big thing in the cloud industry.
Here's I'll go over some of the ways you can integrate Serverless technology in your existing web apps!
Serverless is essentially a system of Function-as-a-Service, where you have certain functions in the cloud, and you get billed by their usage & required computation.
This is a further abstraction from the actual Virtual Machines in common use today, and goes hand-in-hand with a Microservices approach to web development.
But enough about dictionary definitions, let's go to the good stuff:Examples of integrating Serverless with your existing Web App
Reports
Database reports are a pretty common request, often by marketing/business departments to get a better understanding of your users.
This is more common in early-stage applications, before you connect them to proper analytics tools.
Using Serverless, it's quite simple to have a function that runs a report on the database.
We'll use AWS Lambda in this example:- Go to Lambda on your AWS Dashboard:
- Choose "Author from scratch":
- In your Lambda function, add the following code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
'use strict'; module.exports.runReport = (event, context, callback) => { const response = { statusCode: 200, body: { message: 'Result: ', input: event, }, }; const mysql = require('mysql'); const connection = mysql.createConnection({ host: 'localhost', user: 'user', password: 'password', database: 'database', port: 'port' //if you remove this line port defaults to 3306 }); connection.connect(); connection.query('SELECT * FROM users', function(err, results) { if (err) throw err; response.body.message += JSON.stringify(results); response.body = JSON.stringify(response.body); callback(null, response); }) connection.end(); };
- As an easier alternative, get the entire Serverless Boilerplate here
Admin Panel
In most web applications there's some sort of an Admin Panel.
Ideally, the admin panel should be a separate application, to limit potential systemic weaknesses.
Using Serverless, we're able to take advantage of some of the most secure systems available - IAM permissions.
Examples of cool things you could do to further secure your Admin Panel:- Restrict Admin functions permissions - Since Lambda functions have their own IAM roles, you can have very fine-grained permission settings. A great example of this is with DynamoDB.
You can literally give your function access to specific tables with a custom IAM policy:Or another great example where a function can only write items to the table without reading any:1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1509470869566", "Action": [ "dynamodb:BatchGetItem", "dynamodb:DescribeTable", "dynamodb:GetItem", "dynamodb:GetRecords", "dynamodb:ListTables", "dynamodb:Query", "dynamodb:Scan" ], "Effect": "Allow", "Resource": "arn:aws:dynamodb:YOUR-REGION:YOUR-AWS-ID:table/TABLE-NAME" } ] }
1 2 3 4 5 6 7 8 9 10 11 12 13
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Stmt1509470869566", "Action": [ "dynamodb:PutItem" ], "Effect": "Allow", "Resource": "arn:aws:dynamodb:YOUR-REGION:YOUR-AWS-ID:table/TABLE-NAME" } ] }
- Combine API Gateway with Cognito User Pools for authentication - This is quite complex, but this guide has a pretty good walkthrough. In the following days (probably weeks) I'll try to add this to the boilerplates repository.
- Write the entire Admin Panel on Serverless - If your app doesn't have a fully fledged Admin Panel yet (and you understood the last 2 items on the list), This could offer both a high level of security as well as a great way to integrate Serverless into an important but not-yet-customer-ready parts of your system.
Cron Jobs
Most applications have some form of Cron Jobs, but more often than not,
there's a good chance that you don't have a lot of logging/analytics for your Cron Jobs.
With CloudWatch you can schedule functions to run every minute/hour/day/week, just like a normal Cron Job.
Combine that with CloudWatch Alarms, and you have both a logging system and an alarm system in case something goes wrong.
These were just a few examples of how you could integrate Serverless into your web app right away.
In the future, I'll try to work on the boilerplate repository, to add more cases.Posted in Technology- Go to Lambda on your AWS Dashboard:
View-specific JS Files in Sails.js
One thing I really loved about Meteor, is that you can fine-tune which files are included (and the order of inclusion).
This is especially useful when structuring everything in small Meteor packages.
So for example, if you simply want to add relevant client JS files (on package.js):page-login.html:1 2 3 4
api.addFiles([ 'client/page-login.html', 'client/page-login.js', ], 'client');
page-login.js:1 2 3 4 5 6 7
<template name="PageLogin"> <form id="login-form"> <input name="username" type="text" /> <input name="password" type="password" /> <input id="submit-login" type="submit" /> </form> </template>
Together with specific Template namespaces, it allows you to have template-specific JS code that doesn't interfere with other templates. I looked for a way to have that feature in Sails.js.1 2 3 4 5 6
Template.PageNewDomain.events({ 'submit #login-form': function (event, template) { event.preventDefault(); //handle form submission.. } });
Instead of trying to implement the entire complicated Template rendering engine, I figured it should be enough if every view gets a corresponding JavaScript file that is optionally loaded with said view.How it should work
- Each View in the views/ folder has a name, let's create a corresponding JS file with the same name
- On Sails.js, JavaScript files are stored separately in the js/ folder, let's store all view-specific JS files under js/views/
- JS filenames should be the same as view filenames. views/dashboard/login.ejs will have a JS file named js/views/dashboard/login.js
How to implement
- add this to config/views.js:This is so that we're able to check if a JS file exists.
1 2 3 4
locals: { existsSync: require('fs').existsSync, jsPath: __dirname + '/../assets/js/views/' }
- on the bottom of views/layout.ejs, under blocks.localScripts
1 2 3
<% if (existsSync(jsPath + req.options.controller + '/' + req.options.action + '.js')) { %> <script src="/js/views/<%= req.options.controller + '/' + req.options.action %>.js"></script> <% } %>
- In tasks/pipeline.js in the jsFilesToInject array, we need to remove
js/**/*.js
This is Critical. Otherwise, all JS files under js/views will be automatically included in ALL views.
Instead, to automatically inject other views we can have the following line:js/dependencies/**/*.js
Posted in TechnologyMeteor Alternative to Kadira
or: How to integrate SPM with Meteor
It's been far too long since I wrote a post, life gets super busy sometimes.
At any rate, today I'm going to be writing about something that is searched by quite a lot of people:
An Alternative to Kadira.What is Kadira?
Kadira is the only Cloud-based Meteor Debugging tool out there.
If you're familiar with tools like New Relic, Kadira is basically a lean version of that.
It allows you to see live bugs/errors coming from your application, with a full backtrace so you know which part of the application is causing the problem (to some extent). It also has limited tools for reporting/statistics, so you can see if there's a great uptick of bugs lately or a certain type of bug after introducing a new feature.Why look for a Kadira Alternative?
It was recently published that the founder and maintainer of Kadira has moved away from Meteor.
Leaving the fate of Kadira very uncertain. In fact, a full year and a half before the announcement,
there weren't any changes to Kadira's feature set.
What disappointed me the most was that Kadira's source wasn't released, so on the one hand it won't be maintained any longer, but on the other hand, there's no option for the community to step in.
On top of that issue, Kadira is quite limited, searching/navigating through issues is very difficult and at times - impossible. there's a lot of repeated bugs that are not registered correctly (without any backtrace or info), making it very hard to find which is a Kadira bug, and which is an actual bug in my application.
That's why I thought that it was time to seek an alternative.Who plays nice with Meteor?
Most of the major services (New Relic, AppDynamics), didn't support Meteor, or if they did - it was a very limited support, and considering the price point (in the hundreds, sometimes thousands monthly), I expected to have a complete turnkey solution with minimal integration issues.
After looking at a few posibilities, I decided to go with SPM from Sematext.
This tool is not the most popular debugging tool in the world, but their API is clear, easy to use, and their interface is quite nice as well.Implementing SPM Debugger in Meteor
This can be done with 2 easy steps- Add the following to your package.js or .meteor/packages for chaotic packageless projects (SHAME, SHAME):
1 2 3 4 5
Npm.depends({ 'spm-agent-nodejs': '1.30.2', 'winston': '2.3.0', 'winston-logsene': '1.2.1' })
- Add the following code to your Server-side code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/* Loading SPM Monitoring Agent */ var spmStart = function() { process.env.NODE_OPTIONS = '-r spm-agent-nodejs'; var logsene_token = LOGSENE_TOKEN; //Insert Logsene token here var spmAgent = Npm.require('spm-agent-nodejs'); //Logsene var winston = Npm.require('winston'); var logsene = Npm.require('winston-logsene'); var logger = new winston.Logger(); logger.add(logsene, {token: logsene_token, type: 'logs'}); // Overriding Meteor Error function, simply adding the // logger before the original function runs var util = Npm.require('utils'); var errorFunc = Meteor.Error; Meteor.Error = function(error, reason, details) { logger.error('Error: ' + error, { error: error, reason: reason, details: details, stack: Error().stack, tags: ['error', 'winston'] }); errorFunc.call(this, error, reason, details); }; util.inherits(Meteor.Error, errorFunc); }; spmStart();
Special thanks to Wojtek Krysiak for adding inheritance hereI suggest creating a separate file in your Meteor Project (or better yet, a separate package!)
I might organize the code snippet and add it to GitHub at a certain point (fingers crossed).
Until next time!Posted in Technology- Add the following to your package.js or .meteor/packages for chaotic packageless projects (SHAME, SHAME):
Microsoft Buys LinkedIn for $26.2 Billion
In a move that may surprise many, Microsoft just made a deal to buy LinkedIn,
for the amount of $26.2 Billion.
How does this compare to the Whatsapp deal (last huge tech buy)? Well, since a picture is worth a thousand words, I've decided to make an infographic (almost a picture):Posted in Technology