SpankChain Development Update 002 — November 3, 2017

The SpankChain team has been hard at work the past week finalizing the details of the now-live Global Token Sale Event! We at SpankChain are very community focused and like to keep everyone updated on our progress so here are the latest development updates from the previous week!

The SpankChain Global Token Sale is now live!

The SpankChain auction is now live and actively accepting bids. There are also several tutorial videos available on both the SpankChain YouTube Channel, as well as on our auction page to help guide users through the process of bidding and selecting their market caps. The team has been working around the clock to get the token sale ready for the community! after researching a multitude of different auction models, the SpankChain team felt that this current structure was, to date, the fairest means of conducting a token sale. One of our primary goals with the auction was to make participation a simple and straightforward process for everyone. In the future, we hope that this may serve as a secure and fair model for token sales.

To begin the bidding process, check out our state channel auction. If you’re curious to learn more, read about it here.

An Auction Model for Future Projects

To create the unique model we envisioned for our sale, and considering there is (at time of writing) no precedent for an auction model quite like this, we needed to make sure that the debugging process would be a simple one. Hybrid chain systems are, generally speaking, notoriously difficult to debug! In order to ensure successful deployment, the SpankChain Development team segmented itself by front-end, server-side, and smart contract project groups.

Our devs have a tendency to move fast and develop in parallel so it was clear early on that it would be cumbersome to run tests by completing auctions one at a time and even more burdensome to coordinate. We found a solution by creating multiple contracts representing different states of the auction that were easily recognisable via ENS names like spankpurchasing.test, spankprocesssing.test, etc.

For anyone whose interested, you are welcome to see them on Rinkeby for the next few days until the .test domain name expires. This led us to the idea of taking a contract address or ENS name as a querystring parameter.

When we looked up from our laptops, we realized we created the first (kick) AaaS (Auction as a Service) system.

This is just the very beginning. We are exploring ways to make this generally available to future projects, so please reach out to us if you have ideas (or like our auction model and want to use it). We hope this is valuable and we can look back and say it was “one small step for our dev team, one giant leap forward for the ecosystem.”

Synchronous Network Operations in JavaScript

The reality is that asynchronous programming is hard, even more so in JavaScript. Here’s “one weird trick” we found to make web3 easier to manage. Below we share how we turned core JavaScript libraries from asynchronous code to synchronous code.

Fortunately node-XMLHttpRequest — the library used by Web3 to make HTTP requests from Node — has our back. It faithfully implements XMLHttpRequest specification, including — critically — the `async=false` argument.

This makes it easy to take code which was previously a tangled mess of callbacks:

web3.eth.getBlock(69, (block, err) => {
if (err) throw new Error(err);
block.transactions.forEach(tx => {
web3.eth.getTransactionReceipt(tx.hash, (receipt, err) => {
if (err) throw new Error(err);
console.log(‘receipt:’, receipt);
})
})
})

And re-write it simply, cleanly, and linearly:

let block = web3.eth.getBlock(69)
block.transactions.forEach(tx => {
web3.eth.getTransactionReceipt(tx.hash).forEach(receipt => {
console.log(‘receipt:’, receipt);
})
})

“Wait!” You might be exclaiming, “JavaScript is asynchronous! How can this possibly work?”

We asked same question when we noticed strange behaviour with one of our Node processes: CPU load would spike to 100% while it synchronized the blockchain state… a process which — we thought — was entirely network bound.

Upon further investigation, we found a marvelous hack, deep in the guts of node-XMLHttpRequest:

  var syncFile = “.node-xmlhttprequest-sync-” + process.pid;
fs.writeFileSync(syncFile, “”, “utf8”);
var downloadScript = `
var http = require(‘http’);
…;
response.on(‘end’, () => fs.unlinkSync(‘${syncFile}’));
`;
spawn(process.argv[0], [“-e”, downloadScript])
while (fs.existsSync(syncFile)) {
// Wait until the sync file has been removed
}

Yep, you’re reading that correctly: synchronous HTTP requests are implemented by spawning a sub-process to perform the download while the main process spins waiting until the synchronization file is removed by the sub-process (at which point it reads the result from another file written by the sub-process).

This became a real problem for the SpankChain team as we moved from testing on Testnet, where blocks only have a few transactions, to Mainnet, where blocks would frequently have 100+ transactions, and our synchronization process started to fall farther and farther behind.

To avoid re-writing all of our existing code with callbacks, we built a small wrapper to wrap web3 calls in a promise, which we could `await` to simulate synchronously:

let cb2promise = (objAndFunc, …args) => {
let [objName, methodName] = objAndFuncName.split(‘.’);
return new Promise((res, rej) => {
web3[objName][methodName](…args, (err, result) => {
err? rej(err) : res(result);
})
})
};

So our code becomes:

let block = await web3call(‘eth.getBlock’, 69);
block.transactions.forEach(tx => {
let receipts = await web3Call(‘eth.getTransactionReceipt’, tx.hash);
receipts.forEach(receipt => {
console.log(‘receipt:’, receipt);
})
})

And we’re able to continue working asynchronously with minimal code changes and no hint of callback soup.

PS: for completeness, this is very similar to the functionality offered by Bluebird’s `Promise.promisify`.

Thanks for keeping up with the SpankChain Dev updates, the team is extremely excited to be able to share this journey with our community and we look forward to being able the share the news of a successful completed ICO with all of you! To participate in the SpankChain Global Token Sale and purchase SPANK tokens please follow the link here to the SpankChain Auction page!


Connect with SpankChain

To learn more about SpankChain please visit our website, follow us on Twitter, and join our growing Discord community.