Buying An Image -- Sending Transactions

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Million Ether Homepage course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Million Ether Homepage, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Million Ether Homepage
  • [00:00 - 00:08] Now that we have a script that can read an image, let's color each pixel on the blockchain. What we're going to do is iterate over each pixel and send a transaction for each pixel we want to color.

    [00:09 - 00:16] Of course, this can be a lot of transactions, especially if the image is large. But the idea is that someone is purchasing a scarce pixel for a long period of time.

    [00:17 - 00:26] So it's not that big of a deal if it takes a while to buy the whole image. The first thing we need to do is connect to our web three node, type const web three equals require web three, and then create a new instance.

    [00:27 - 00:35] We'll set the provider to the HTTP provider at localhost 8545. Here, I'm using the HTTP provider, but it's worth looking into the IPC provider too.

    [00:36 - 00:44] Next, we need to get a handle on our contract. We'll do this like we have before by loading the ABI and looking up the contracts deployed address.

    [00:45 - 01:08] Because we're sending transactions, we'll also need the sending account address . Normally, you'd configure this as an environment variable or command line argument, but we can hard code it for now.

    [01:09 - 01:32] Now, with this contract, when we loop over each pixel, instead of logging it, we want to call the color pixel method on the contract to send the transaction. We do that by writing map.methods.colorpixel, then we pass the x position, the y position, and then the pixel as a hexadecimal string.

    [01:33 - 01:48] And then we send from our account. Remember that each pixel can be placed in a particular position on the board, so as we write each pixel, we add the x-poss and the y-poss as an offset.

    [01:49 - 01:57] We can control the location of the image this way. To try this out, make sure that you have getth running, and you've unlocked your account, the same account that you coded above.

    [01:58 - 02:07] Also, make sure that you have a minor running. One thing to note is that this can send a lot of transactions, and so you need to make sure that you have enough miners running.

    [02:08 - 02:14] Here, I'm going to start three minor threads in getth. Now we can try it out and watch in our browser as the pixels load.

    [02:15 - 02:43] Nice! For small images, this probably works for you. But if you try it with larger images, you'll notice that you have missing pixels.

    [02:44 - 03:07] The reason is, each node limits the number of un-mined transactions allowed from ascending address. Instead, we should issue our transaction in chunks, and then wait for them to be mined.

    [03:08 - 03:17] To do this, we can wrap our pixel writing code in an async function. What we'll do is submit a group of transactions, and then wait for them to be mined before we submit the next group.

    [03:18 - 03:26] This will allow our network time to catch up. Each time we send a transaction, the return value is a promise, and this promise is fulfilled when the transaction is mined.

    [03:27 - 03:31] We can store that promise in a list of promises. We don't need to wait for every single transaction.

    [03:32 - 03:44] Instead, we can just wait for, say, every 128, or every 64 transactions. So if i mod 128 is equal to 0, we'll pause and wait for at least one transaction to be mined.

    [03:45 - 03:53] Here, we're using promise.race, which will continue as soon as the first promise in the group is resolved. If you wanted more reliability, you could use promise.all instead.

    [03:54 - 03:59] At the end, we'll call send pixels and then wait for it to finish. Now, let's try this out with a bigger image.

    [04:00 - 04:28] This might take a little while to run. There we go! We can color pixels using an image, but we still have the problem that these pixels are open for anyone to write over for free.

    [04:29 - 04:37] So let's modify our contract so that you have to send funds and bid for each pixel in order to control it. Thank you.

    [04:38 - 04:51] [end] [end]