Nimiq Stores for SvelteJS

Hello everyone!

as a side-project, I created reactive Nimiq stores for the SvelteJS framework.

What is SvelteJS?

SvelteJS is a compiled front-end framework, which has been around for a few years, but completely redesigned itself with version 3 not too long ago. It is a reactive front-end framework with the same goals as React and Vue, but instead of shipping a big runtime library to the browser, this framework compiles an app with only the minimal required code and can thus have a much much smaller download size and better performing DOM updates. Granted, its feature set is smaller than React and Vue, but it also requires much less code.

I recommend to go through the tutorial, which explains Svelteā€™s concepts step-by-step:

What are Nimiq Stores for Svelte?

Similar to Redux in React, or Vuex in Vue, Svelte also has the concept of app-wide stores that hold state which can be used from all components. These stores are very simple ES6 functional modules that can be extended and combined to do nearly anything, and they are often compared to React Hooks as well.

Nimiq Svelte Stores wrap the Nimiq Client API (available in Nimiq Core v1.5) and provide blockchain state to Svelte apps through these stores, automatically handling network subscriptions for consensus, balances, transactions, etc. and updating state live. That means you donā€™t have to write any of this code!

Have a look at the example app:
https://nimiq-svelte-stores.netlify.com
and the code for it:
https://github.com/sisou/nimiq-svelte-stores/blob/master/src/App.svelte

If you have any questions about Svelte or these stores, please ask!

Happy coding!
Sƶren

6 Likes

I just released version 1.1.0, now with Typescript types!

Nothing changes on how you use the library, but now your editor can automatically pick up the types for the stores, and TS can compile with the correct types.

3 Likes

Is this project still alive? Iā€™d like to use, iā€™m learning svelte and I have an idea, Iā€™d like to test it.

Hi!

Yes, it is! I noticed that the example app was broken (because I restructured the demo application some time ago), but I just fixed it, so now itā€™s running again at
https://nimiq-svelte-stores.netlify.app

If you have any questions, feel free to ask here or create an issue in Github :+1:

1 Like

Hi

thank you.

Iā€™ll test it if someday I have some free time. If I have any doubts iā€™ll contact with you!

Hi Soeren

iā€™ve playing with Svelte and the Nimiq Stores and it works fine but as I can see some of the functions are not implemented. Iā€™m quite ignorant with svelte and javascript. :sweat_smile:

Is there any possibility to add functions to connect with Hub? Iā€™d like to be able to send transactions with my Svelte app using my account stored on Hub.

Let me know if itā€™s possible

Hi!

The svelte-stores only cover the Nimiq Network part, you are right.

To create a transaction with the Hub, you need to use the HubApi, which is documented here:

You can then give the serializedTx of the Hub result to client.sendTransaction(). client being an export of the svelte-stores.

I hope this makes sense. If you need more help, I am happy to provide example code. :slight_smile:

1 Like

thank you, Iā€™ll investigate, If I have problems Iā€™ll let you know

Hi Soeren,

how are you doing?

Iā€™ve tried to pick up one address form my hub (I can do that) and the add is to ā€˜accountsā€™ svelte store, but I donā€™t know what Iā€™m doing wrong, Look at handleClick() function.

Iā€™ve tried everything but Iā€™m not an expert with javascript, so I donā€™t know how to continue:

Here is the code of the component:

<script>
	import {
    accounts,
	} from 'nimiq-svelte-stores';

  let address = getAddress()

  const hubApi = new HubApi('https://hub.nimiq.com');

  async function getAddress() {
      const result = await hubApi.chooseAddress({ appName: 'Hub API Docs' });

      try {
        return result.address;
      } catch (error) {
        throw new Error(result.address);
      }
  };

  function handleClick() {
    address = getAddress();
    let label = '';
    console.log(address);
    accounts.add({address, label});
	};


</script>

<button on:click={handleClick}>
	Choose Address
</button>

{#await address}
	<p>...waiting</p>
{:then address}
	<p>The address is {address}</p>
{/await}

Maybe you can guide meā€¦ :wink: Iā€™d like to account both, address and labelā€¦

1 Like

Hi!

Itā€™s great that you are getting started with Javascript, Nimiq and Svelte!

Here is a working component, I am explaining what I changed below:

<script>
  import {
    start as startNimiq,
    accounts,
  } from 'nimiq-svelte-stores';
  import HubApi from '@nimiq/hub-api';

  const hubApi = new HubApi('https://hub.nimiq.com');

  // Connect to the Nimiq network, to automatically get account balances in the accounts store
  startNimiq();

  async function getAccount() {
    const account = hubApi.chooseAddress({ appName: 'Hub API Docs' });

    try {
      return await account;
    } catch (error) {
      // TODO: Handle the error instead of throwing
      throw error;
    }
  };

  async function handleClick() {
    const account = await getAccount();
    console.log(account);
    accounts.add(account);
  };
</script>

<button on:click={handleClick}>
  Add Address
</button>

<h2>Addresses</h2>

{#each $accounts as account}
  <p>
    Address: {account.address.toUserFriendlyAddress()} /
    Label: {account.label} /
    Balance: {account.balance / 1e5} NIM
  </p>
{/each}

Changes

  • Import HubApi from NPM package: import HubApi from '@nimiq/hub-api (not necessary if you added the HubApi as a <script> in index.html)
  • Instead of displaying the selected account/address in the HTML, I am listing all accounts in the accounts store (needs to be used with the dollar sign to tell Svelte that itā€™s a store: {#each $accounts as account}
  • The chooseAddress() HubApi method returns both the address and the label. So instead of only returning the address from the getAddress function, I renamed it to getAccount and return the whole object, including the label.
  • I am awaiting the getAccount method, because using the Hub is always an asynchronous operation.
  • I added the Nimiq library to the public/index.html file, above the bundle.js script:
	<!-- add this: --><script defer src="https://cdn.nimiq-testnet.com/web.js"></script>
	<script defer src='/build/bundle.js'></script>
  • To automatically get the balances from the network for each added account, I am importing { start as startNimiq } from 'nimiq-svelte-stores' as well, and calling it when the app starts, so the network connection is started.
  • The account in the the $accounts store is a native Nimiq.Account object, so to display the nice address, we have to use its toUserFriendlyAddress() function in the HTML.

I hope this helps you forward and helps you understand better how things work. If you have any more questions, feels free to ask here, or we can also have a call about it :wink:

Kind regards,
Sƶren

1 Like

Thank you very much Sƶren, it has been very helpful and Iā€™ve learnt some more things about JavaScript. Usually I code with c++ and javascript itā€™s quite different, but Iā€™m learning a lot.

Iā€™m coding one app that will use nimiq blokchain. Iā€™ve all on my mind, some components are working and other not. When all components work, I need to glue them and the app will be ready, more or less. Iā€™m not good with css and Iā€™m not a good designer, so maybe it will be quite ugly. hanks again.

If you donā€™t mind, Iā€™ll contact with you again if I get stuck, ok?

Thanks again!

Hi Sƶren,

sorry again, but I got stuck.
Iā€™ve added your code to my svelte app, it works properly. I can read transactions, receiver, sender, amountā€¦ but I canā€™t read the extraData.

Here is my code:

	{#each $transactions as tx (tx.transactionHash.toPlain())}
		<tr>
			<td>{new Date(tx.timestamp * 1000).toLocaleString()}</td>
			<td>{tx.sender.toPlain()}</td>
			<td>{tx.recipient.toPlain()}</td>
			<td>{tx.value / 1e5} NIM</td>
			<td>{tx.state}</td>
			<td>{tx.extraData.toS()}</td>
		</tr>
	{/each}

I have tried with tx.extraData.toPlain() , or tx.extraData.toString() or tx.extraData.toString(), but I donā€™t know how to do it.

thanks again. :wink:

Hi!

I believe extraData is an object that, in a regular transaction, contains the property raw, which is a hex string.
So to get it into ASCII you can do

Nimiq.BufferUtils.toAscii(Nimiq.BufferUtils.fromHex(transaction.extraData.raw))

Or any other hex-to-character transformation.

thank you again for your time, it has been helpful.

After tons of trials the correct way was this:

<td>{Nimiq.BufferUtils.toAscii(tx.data.raw)}</td>

Hi Sƶeren,

One question, do you mind if the next time i contact with you via Telegram? Iā€™m on
ā€œNimiq Coders Dojoā€ group and Iā€™ve seen you around there,

Yes, definitely! Iā€™m happy to help over Telegram!

1 Like

Hi Sƶren.

How are you doing? You are from Germany, right? Maybe you are interested on this event: https://www.meetup.com/de-DE/Svelte-js-Meetup/

You can promote this code and this project there

There are other Svelte events along Europe: https://svelte-community.netlify.app/events