C Library for Working with Waves

waves-c

C library for working with Waves.

Building

This package uses CMake version 3.9 (or newer) for building and it depends on development package of OpenSSL version 1.1 (or newer).

To build it on Linux, install the OpenSSL 1.1 development package (usually called something like openssl-dev), then run the following commands:

cmake .
make

On macOS, install OpenSSL using brew, then pass the OpenSSL root directory path as a CMake parameter as follows:

brew install openssl@1.1
cmake -DOPENSSL_ROOT_DIR=/usr/local/opt/openssl@1.1 .
make

Packaging

By default, the CMake configuration enables all supported CPack generators. Check out the CPACK_GENERATOR option for the list of supported CPack generators (see src/CMakeLists.txt). CPack generator can be overridden as follows:

cmake -DCPACK_GENERATOR=RPM .

Installing

If there is no suitable CPack generator in the CPACK_GENERATOR list, then the only option is running make install.

Quick Start

For a quick start, we took the bcdev's waves_vanity source code as a basis. Thanks to bcdev for providing that!

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/waves-c
License: Apache-2.0 license

#waves #c  #blockchain  #smartcontract 

C Library for Working with Waves

Cryptocurrency Library Based on Go for Waves Platform

go-lib-crypto

go-lib-crypto is a unified crypto library for Waves Platform. It has a unified set of functions corresponding with unified-declarations.

This library meant to be used in client applications. That's why its API is relatively simple.

The following could be done using the library:

  • Calculation of a hash digest of various hash functions used by Waves
  • Encoding and decoding of byte slices in BASE58 and BASE64 string representation
  • Key pair generation from seed phrase
  • Waves address generation and verification
  • Random seed phrase generation and verification
  • Signing of bytes message
  • Verification of signed message

Installation and import

go get -u github.com/wavesplatform/go-lib-crypto
import "github.com/wavesplatform/go-lib-crypto"

Short API reference with examples

Instantiation

For the purpose of unification the API of the library made in form of the interface. To instantiate the un-exported structure that implements the interface call the NewWavesCrypto function.

crypto := wavesplatform.NewWavesCrypto()

Working with hashes

The three hash functions used by Waves are supported:

  • SHA-256
  • BLAKE2b-256
  • Keccak-256 (legacy version)

Every hash functions accepts one parameter of type Bytes. The Bytes type wraps a slice of bytes.

package main

import (
    "encoding/hex"
    "fmt"
    "github.com/wavesplatform/go-lib-crypto"
)

func main() {
    bytes, _ := hex.DecodeString("fd08be957bda07dc529ad8100df732f9ce12ae3e42bcda6acabe12c02dfd6989")
    c := wavesplatform.NewWavesCrypto()
    blake := c.Blake2b(bytes)
    keccak := c.Keccak(bytes)
    sha := c.Sha256(bytes)
    fmt.Println("BLAKE2b-256:", hex.EncodeToString(blake))
    fmt.Println("Keccak-256:", hex.EncodeToString(keccak))
    fmt.Println("SHA-256:", hex.EncodeToString(sha))
}

The output should be like this:

BLAKE2b-256: c425f69e3be14c929d18b2808831cbaeb2733c9e6b9c5ed37c3601086f202396
Keccak-256: 14a0d0ee74865d8d721c4218768b7c39fd365b53f0359d6d28d82dc97450f583
SHA-256: 7ed1b5b6867c0d6c98097676adc00b6049882e473441ac5ff3613df48b69f9f3

See the example on play.golang.org.

Seed and keys generation

One can create a new key pair from the seed phrase. Library defines types for Seed, PrivateKey, PublicKey (wrappers over string) and structure for KeyPair that combines the private and public keys.

The function RandomSeed creates a new random seed phrase of 15 words. The seed generation follows the BIP39 standard.

The keys generation functions KeyPair, PublicKey and PrivateKey accept the seed phrase as its parameters and produces a KeyPair, PublicKey or PrivateKey relatively. In latter two cases the whole key pair is produced, but only a part of it returned to the user.

Here is the example.

package main

import (
    "fmt"
    "github.com/wavesplatform/go-lib-crypto"
)

func main() {
    c := wavesplatform.NewWavesCrypto()
    seed := c.RandomSeed()
    fmt.Println("SEED:", seed)

    pair := c.KeyPair(seed)
    fmt.Println("PAIR:", "PRIVATE KEY:", pair.PrivateKey, "PUBLIC KEY:", pair.PublicKey)

    sk := c.PrivateKey(seed)
    fmt.Println("PRIVATE KEY:", sk)

    pk := c.PublicKey(seed)
    fmt.Println("PUBLIC KEY:", pk)
}

Waves address generation

There is an Address type which wraps the string. An address could be created from PublicKey or Seed using functions Address or AddressFromSeed. In both cases the WavesChainID byte should be provided as second parameter. It is possible to verify the correctness of an Address string using functions VerifyAddressChecksum or VerifyAddress. The first function checks that the address has correct length and version and the built-in checksum is correct. The second one additionally checks that the address contains the correct WavesChainID.

package main

import (
    "fmt"
    "github.com/wavesplatform/go-lib-crypto"
)

func main() {
    c := wavesplatform.NewWavesCrypto()
    seed := c.RandomSeed()
    fmt.Println("SEED:", seed)

    pair := c.KeyPair(seed)
    fmt.Println("PAIR:", "PRIVATE KEY:", pair.PrivateKey, "PUBLIC KEY:", pair.PublicKey)
    
    address := c.Address(pair.PublicKey, wavesplatform.TestNet)
    fmt.Println("ADDRESS 1:", address)
    
    address2 := c.AddressFromSeed(seed, wavesplatform.TestNet)
    fmt.Println("ADDRESS 2:", address2)
    
    fmt.Println("CHECKSUM OK:", c.VerifyAddressChecksum(address))
    fmt.Println("ADDRESS ON TESTNET OK:", c.VerifyAddress(address, wavesplatform.TestNet))
    fmt.Println("ADDRESS ON MAINNET OK:", c.VerifyAddress(address, wavesplatform.MainNet))
}

Try the example.

Signing and verifying

The library offers two functions to sign bytes (SignBytes and SignBytesBySeed) and one to verify a signature (VerifySignature).

Here is the example of using those functions.

package main

import (
    "fmt"
    "encoding/hex"
    "github.com/wavesplatform/go-lib-crypto"
)

func main() {
    bytes, _ := hex.DecodeString("fd08be957bda07dc529ad8100df732f9ce12ae3e42bcda6acabe12c02dfd6989")
    other, _ := hex.DecodeString("54686520696e636f7272656374206d657373616765")

    c := wavesplatform.NewWavesCrypto()
    seed := c.RandomSeed()
    fmt.Println("SEED:", seed)

    pair := c.KeyPair(seed)
    fmt.Println("PAIR:", "PRIVATE KEY:", pair.PrivateKey, "PUBLIC KEY:", pair.PublicKey)
    
    sig1 := c.SignBytes(bytes, pair.PrivateKey)
    fmt.Println("SIGNATURE 1:", hex.EncodeToString(sig1))
    sig2 := c.SignBytesBySeed(bytes, seed)
    fmt.Println("SIGNATURE 2:", hex.EncodeToString(sig2))
    
    fmt.Println("SIGNATURE 1 OK:", c.VerifySignature(pair.PublicKey, bytes, sig1))
    fmt.Println("SIGNATURE 2 OK:", c.VerifySignature(pair.PublicKey, bytes, sig2))

    fmt.Println("SIGNATURE 1 ON OTHER OK:", c.VerifySignature(pair.PublicKey, other, sig1))
    fmt.Println("SIGNATURE 2 ON OTHER OK:", c.VerifySignature(pair.PublicKey, other, sig2))
}

Documentation

go-lib-crypto on GoDoc.

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/go-lib-crypto
License: MIT license

#waves #go  #blockchain  #smartcontract 

Cryptocurrency Library Based on Go for Waves Platform

Library for Create Unit Test with WAVESPLATFORM Node

install

npm install @waves/node-state -D

Usage

cli:

node-state -n -e -o ./state.json or node-state -n -e -o -m typescript ./state.ts

Options:
  --help          Show help                                            [boolean]
  --version       Show version number                                  [boolean]
  --out, -o       Out of result                              [string] [required]
  --config, -c    Path to config file                                   [string]
  --mode, -m      Compile mode [choices: "json", "typescript"] [default: "json"]
  --node, -n      Need up node (port 6869)                             [boolean]
  --explorer, -e  Need up explorer (port 3000)                         [boolean]

Usage example

Step 1. Up the node and create the state

node-state -n -m typescript -o ./tests/state.ts;

Step 2. Write some tests with some test framework

import { NODE_URL, STATE, CHAIN_ID, MASTER_ACCOUNT } from './test/state.ts';
import { transfer, broadcast, waitForTx } from '@waves/waves-transactions';


it('Create transfer transaction', async () => {
    const tx = transfer({ 
        recipient: `alias:${CHAIN_ID}:${MASTER_ACCOUNT.ALIAS}`,
        amount: 1000
    }, STATE.ACCOUNTS.SIMPLE.seed);
    await broadcast(tx);
    await waitForTx(tx.id, { apiBase: NODE_URL }); // Transaction broadcast success!
});

Example of output file (test/state.ts) in typescript:

export const MASTER_ACCOUNT = {
    "SEED": "waves private node seed with waves tokens",
    "ADDRESS": "3M4qwDomRabJKLZxuXhwfqLApQkU592nWxF",
    "PUBLIC_KEY": "AXbaBkJNocyrVpwqTzD4TpUY8fQ6eeRto9k1m2bNCzXV",
    "ALIAS": "master"
};
export const NODE_URL = "http://localhost:6869";
export const CHAIN_ID = "R";
export const NETWORK_BYTE = 82;

export const STATE = {
    "ACCOUNTS": {
        "FOR_SCRIPT": {
            "seed": "yellow pulp memory brick mimic myself hungry amount canal crop service stuff bachelor pilot mention",
            "address": "3MPXEgRCmT5cdsFKkq9x5mbiT3oCQ4ZjYw5",
            "publicKey": "AZkHyW5o11h2RerR2e7tF4mRUZED5aAW33sHAAAkseKY",
            "scripted": true
        }
    },
    "ASSETS": {
        "BTC": {
            "type": 3,
            "version": 2,
            "senderPublicKey": "AXbaBkJNocyrVpwqTzD4TpUY8fQ6eeRto9k1m2bNCzXV",
            "name": "WBTC",
            "description": "WBTC description",
            "quantity": 100000000000000,
            "decimals": 8,
            "reissuable": false,
            "fee": 100000000,
            "timestamp": 1573820086719,
            "chainId": 82,
            "proofs": [
                "5YJF6zKSqMN315phAGDhT2fiKyHkZF3j46YAkwXM4f2THdjw4KFSmvbA5omi12ybWpBuqryJLbC9MdCDNSpRDyYg"
            ],
            "id": "DEtwtnL41USBmnoU4UN1rqhHGBKvLLqpH483TV6GK4Sy"
        },
    }
};

Example of output file (test/state.json) in json:

{
  "ACCOUNTS": {
    "FOR_SCRIPT": {
      "seed": "usual scatter episode relax spy subway tuna around define expect kit wall cupboard list one",
      "address": "3M2a7rdLCfStGjMJVQjmiTYCZUdgs7eYkkR",
      "publicKey": "BsmaQyjqTmMX4mNoYo9RzV9H8GWtMJb6WPcgB2MNRzBU",
      "scripted": true
    }
  },
  "ASSETS": {
    "BTC": {
      "type": 3,
      "version": 2,
      "senderPublicKey": "AXbaBkJNocyrVpwqTzD4TpUY8fQ6eeRto9k1m2bNCzXV",
      "name": "WBTC",
      "description": "WBTC description",
      "quantity": 100000000000000,
      "decimals": 8,
      "reissuable": false,
      "fee": 100000000,
      "timestamp": 1573820268769,
      "chainId": 82,
      "proofs": [
        "nMtaXPFnAAasKhryqbwVco2SHro87X5vsDAwQmBjpprPaG3DVRSfQrNUKjAf3ejQatxQqSEkFCfPdEa74ALomM9"
      ],
      "id": "EeojFwKrozm9mpHvmYt6N5qnwhGTo8ztXpxogcHHYw8s"
    },
    "MASTER_ACCOUNT": {
      "SEED": "waves private node seed with waves tokens",
      "ADDRESS": "3M4qwDomRabJKLZxuXhwfqLApQkU592nWxF",
      "PUBLIC_KEY": "AXbaBkJNocyrVpwqTzD4TpUY8fQ6eeRto9k1m2bNCzXV",
      "ALIAS": "master"
    },
    "NODE_URL": "http://localhost:6869",
    "CHAIN_ID": "R",
    "NETWORK_BYTE": 82
  }
}

Custom config properties

{
    // Assets for deploy to node state
    "ASSETS": {
        "BTC": {                               
            // Required. Name of asset
            "name": "Asset name",
            // Optional. Description of asset        
            "description": "Asset description",
            // Optional. Decimals of asset. Default 8
            "decimals": 4,
            // Optional. Quantity of asset coins. Default 100000000000000
            "quantity": 100,
            // Optional. Reissuable of asset. Default true
            "reissuable": true
        }
    },
    "ACCOUNTS": {
        // Account name for usage from tests
        "FOR_SCRIPT": {
            // Optional. Script for deploy to account. Choices [boolean or "dApp" or base64 string]
            "script": "dApp",
            // Optional. Create alias for account
            "alias": true,
            // Optional. Balance for account
            "balance": {
                // Hash with key in Key of ASSETS and value is coins of asset
                "BTC": 10000000
            },
            // Optional. Data state for account. Not supported, in development.
            "data": {
                // Key of data state
                "someKey": {
                    // Type of field. Can be "integer" of "binary" of "boolean" or "string"
                    "type": "integer",
                    // Value for data state
                    "value": 1000
                }   
            }
        }
    }
}

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/node-state
License:

#waves  #blockchain  #smartcontract #typescript 

Library for Create Unit Test with WAVESPLATFORM Node

Ledger Devices App for Waves Platform

ledger-app-waves

Introduction 🔐

This is a Ledger devices wallet app for Waves platform.

Special thanks to Jean Passot, Cédric Mesnil, and Oto from the Ledger team, Jake Bordens from the Ledger/Birst community for their support and advices. Thanks to the Waves community for trusting the tokens on this application.

For app APDU protocol and an integration manual please take a look at this.

Building 👷

You'll need a Ledger Nano S development environment. More information can be found here.

Also there're my ledger dev env docker image, you can use it to build it.

Nano S

rm -rf bin/ debug/ dep/ obj/ app.hex src/glyphs.c src/glyphs.h && make BOLOS_ENV=/opt/ledger/ BOLOS_SDK=/home/nanos-secure-sdk

Nano X

rm -rf bin/ debug/ dep/ obj/ app.hex src/glyphs.c src/glyphs.h && make BOLOS_ENV=/opt/ledger/ BOLOS_SDK=/home/ledger/sdk-nanox-1.2.4-1.3

Blue

rm -rf bin/ debug/ dep/ obj/ app.hex src/glyphs.c src/glyphs.h && make BOLOS_ENV=/opt/ledger/ BOLOS_SDK=/home/blue-secure-sdk/

Installation 📲

You can download the official version of this application, signed and verified by the Ledger team, from the official Ledger Live application.

Building and installing from the source code is usually required in order to develop or customize the application. In addition, you will receive a warning that this application was received from an unreliable source. Try to avoid this, it may be unsafe.

If you build the app not in the Docker, but in your host OS then just call make load. Note that you should have the python env with ledgerblue installed. If you can't install ledgerblue, try install the dependencies into your system. There're some more details also.

If you use Docker to build the app, then call this from app root on you host OS:

Nano S

python -m ledgerblue.loadApp --appFlags 0x240 --path "44'/5741564'" --curve secp256k1 --curve ed25519 --tlv --targetId 0x31100004 --delete --fileName bin/app.hex --appName Waves --appVersion 1.1.0 --dataSize 64 --icon 010000000000ffffffffffffff7ffe3ffc1ff80ff007e003c003c007e00ff01ff83ffc7ffeffffffff

Nano X

Note that at the time of publication of this manual (March 2020), the installation of your applications is possible only on special devices for developers.

python -m ledgerblue.loadApp --appFlags 0x240 --path "44'/5741564'" --curve secp256k1 --curve ed25519 --tlv --targetId 0x33000004 --delete --fileName bin/app.hex --appName "Waves" --appVersion 1.1.0 --dataSize 256 --icon 010000000000ffffff000030001ec00ff807ffe3fff97ffc0ffe013f8007c0000000

Blue

python -m ledgerblue.loadApp --appFlags 0x240 --path "44'/5741564'" --curve secp256k1 --curve ed25519 --tlv --targetId 0x31010004 --delete --fileName bin/app.hex --appName "Waves" --appVersion 1.1.0 --dataSize 0x0000000000000100 --icon 04f9efe900f9f9f900fadaca00fae4da00fbbb9b00fc9c6c00fcb18c00fd925d00fe7e3e00fe691e00ff5f0f00ffc0a000ffe0d000ff601000ffffff00ff55000011111111112176f8ffffffffffffffffff8f671211111111111111111153f9ffffffffffffffffffffffffff9f351111111111111150ffffffffffffffffffffffffffffffffff05111111111121faffffffffffffffffffffffffffffffffffaf1211111111f4ffffffffffffffffffffffffffffffffffffff4f11111121ffffffffffffffffffffffffffffffffffffffffff121111a0ffffffffffffffffffffffffffffffffffffffffff0a1111f5ffffffffffffffffffffffffffffffffffffffffff5f1131ffffffffffffffffffffffddffffffffffffffffffffff1351ffffffffffffffffffffdfccfdffffffffffffffffffff1591ffffffffffffffffffffcdeedcffffffffffffffffffff19f2ffffffffffffffffffdfeceecefdffffffffffffffffff2ff6ffffffffffffffffffcdeebbeedcffffffffffffffffff6ff7ffffffffffffffffdfecbeffebcefdffffffffffffffff7ff8ffffffffffffffffcdeefbffbfeedcffffffffffffffff8fffffffffffffffffdfecbeffffffebcefdffffffffffffffffffffffffffffffffcdeefbffffffbfeedcffffffffffffffffffffffffffffffdfecbeffffffffffebcefdffffffffffffffffffffffffffffcdeefbffffffffffbfeedcffffffffffffffffffffffffffdfecbeffffffffffffffebcefdffffffffffffffffffffffffcdeefbffffffffffffffbfeedcffffffffffffffffffffffdfecbeffffffffffffffffffebcefdffffffffffffffffffffcdeefbffffffffffffffffffbfeedcffffffffffffffffffdfecbeffffffffffffffffffffffebcefdffffffffffffffffcdeefbffffffffffffffffffffffbfeedcffffffffffffffffcdeefbffffffffffffffffffffffbfeedcffffffffffffffffdfecbeffffffffffffffffffffffebcefdffffffffffffffffffcdeefbffffffffffffffffffbfeedcffffffffffffffffffffdfecbeffffffffffffffffffebcefdffffffffffffffffffffffcdeefbffffffffffffffbfeedcffffffffffffffffffffffffdfecbeffffffffffffffebcefdffffffffffffffffffffffffffcdeefbffffffffffbfeedcffffffffffffffffffffffffffffdfecbeffffffffffebcefdffffffffffffffffffffffffffffffcdeefbffffffbfeedcffffffffffffffffffffffffffffffffdfecbeffffffebcefdfffffffffffffffff8ffffffffffffffffcdeefbffbfeedcffffffffffffffff8ff7ffffffffffffffffdfecbeffebcefdffffffffffffffff7ff6ffffffffffffffffffcdeebbeedcffffffffffffffffff6ff2ffffffffffffffffffdfeceecefdffffffffffffffffff2f91ffffffffffffffffffffcdeedcffffffffffffffffffff1951ffffffffffffffffffffdfccfdffffffffffffffffffff1531ffffffffffffffffffffffddffffffffffffffffffffff1311f5ffffffffffffffffffffffffffffffffffffffffff5f1111a0ffffffffffffffffffffffffffffffffffffffffff0a111121ffffffffffffffffffffffffffffffffffffffffff12111111f4ffffffffffffffffffffffffffffffffffffff4f1111111121faffffffffffffffffffffffffffffffffffaf12111111111150ffffffffffffffffffffffffffffffffff051111111111111153f9ffffffffffffffffffffffffff9f351111111111111111112176f8ffffffffffffffffff8f67121111111111

Debugging 🙇

To simplify the development and debugging process, it is recommended to follow the Ledger debugging instructions and try to find a solution of your problem here. All this has been tested only with the Ledger Nano S.

  1. Install a debug firmware (according to the instructions above)
  2. Install a custom CA for PIN bypass (according to the instructions above)
  3. Build and use USBTool (according to the instructions above).

Hint: before that on Mac OS X you should install a libusb-compat package: brew install libusb-compat, then just call make clean && make from the app root

  1. Change debug flag in Makefile to DEBUG = 1
  2. Build and install the app adding the --rootPrivateKey key from the second step

Now the device should ask you only one confirmation instead of several! Take care of your buttons, fingers and time 😊

  1. Start usbtool on the PC, then your app on Ledger device, send some APDU and look at the debug output in usbtool stdout!
  2. Check the Ledger device emulator, but at the time of writing (March 2020), it does not support most system calls. For now it perhaps only suitable for debugging an app UI on Ubuntu.

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/ledger-app-waves
License: MIT license

#waves  #blockchain  #smartcontract #c 

Ledger Devices App for Waves Platform

Waves SDK for Android

WavesSDK is a collection of libraries used to integrate Waves blockchain features into your Android application

What is Waves?

Waves is an open source blockchain platform.

You can use it to build your own decentralised applications. Waves provides full blockchain ecosystem including smart contracts language called RIDE.

How does the blockchain network work?

There is a huge collection of nodes deloyed by miners that store all of the network information in the chain of blocks (aka blockchain), process requests and can add new transactions to the network after checking their compliance with the rules. The miners are rewarded with the network coins called MRT. 

The main advantage of this technology is that each node is a synchronized copy of the main blockchain: it means that the information is stored decentralized and won't be overwritten globally if one of the users changes it at one of the node storages. This can garantee that the user's information will stay fair and unchangable. 

The important addition is that the service built using Waves blockchain looks like a usual web application and doesn't make user experience more difficult. 

You can read the Waves node description and the definitions page for a better understanding of the blockchain functionality.

Easy start with WavesSDK

To build your first Waves platform integrated application and start using all of the blockchain features please go directly to the Waves Android SDK QuickStart tutorial and follow the instructions.

Waves SDK structure

There are three main SDK services that provide the blockchain interactions:

  • Waves Crypto handles interaction with crypto part of blockchain, allows to generate seed-phrases, convert public and private keys, obtain and verify addresses, translate bytes to string and back, sign the data with a private key, etc.
  • Waves Models contain models of transactions and other data transfer objects that are needed for building correct services.
  • Waves Node Service allows the application to cooperate directly with the blockchain: you can create transactions, broadcast them and load data from the node using these features. This is the main part of the SDK.
  • Waves Data Service suggests the easier way to access the data that is stored in the node. The methods presented in this service are the most efficient way to read blockchain data but do not help writing it.
  • Waves Matcher Service contains the methods that give ability to integrate Waves DEX (decentralized exchange platform) features into the iOS application. You can collect and add users' orders and work with exchange transactions using this service.
  • Mobile-Keeper is part of Waves client app, it designed to send or sign transactions created in third-party applications, but keep your seed-phrase in the safe place and do not show it to that applications

Testing

To test your app you can use Testnet. This is a Waves Mainnet duplicate where it's possible to repeat the real accounts structure without spending paid WAVES tokens. You can create multiple accounts, top up their balances using Faucet (just insert the account address to the input field and get 10 test tokens) and deploy RIDE scripts (as known as "smart contracts" or "dApps") using Waves RIDE IDE.

Useful links

Support

Keep up with the latest news and articles, and find out all about events happening on the Waves Platform.

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/WavesSDK-android
License: MIT license

#waves  #blockchain  #smartcontract #android #kotlin 

Waves SDK for Android

WavesSDK: integrate Waves Blockchain Features Into IOS Application

WavesSDK – it is mobile libraries for easy and simple co-working Waves blockchain platform and any mobile app

Easy start with WavesSDK

Library contains 3 main parts

  • Waves Crypto – section responsible for generating seed-phrases, converting it into public and private keys, obtaining address, verifying, translating bytes into a string and reverse, signing the data with a private key and other. All things that prepare to interact with crypto part of blockchain
  • Waves Models – models of transactions and other data transfer objects for work with Waves Services, also it is release signing data with private key
  • Waves Services – net services for sending transactions and getting data from blockchain

Testing

You can use Explorer Testnet for testing your app with libs. You can add test-Waves to your balance at the explorer in side menu from Faucet. And you can check any sent transactions on Wavesexplorer in Main or Test Net

Links

Blockchain for the people

Keep up with the latest news and articles, and find out all about events happening on the Waves Platform.

Demo

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/WavesSDK-iOS
License: MIT license

#waves  #blockchain  #smartcontract 

WavesSDK: integrate Waves Blockchain Features Into IOS Application

Docker Image with Private Custom Node for Waves Platform

Waves private node

The image is useful for developing dApps and other smart contracts on Waves blockchain. Uses actual Mainnet version by default.

Getting started

To run the node,
docker run -d --name waves-private-node -p 6869:6869 wavesplatform/waves-private-node

To view node API documentation, open http://localhost:6869/

Use Stagenet version

If you would like to try Stagenet version of Waves Node, then use docker tag stagenet:
docker run -d --name waves-private-node -p 6869:6869 wavesplatform/waves-private-node:stagenet

Preserve blockchain state

If you want to keep the blockchain state, then just stop the container instead of killing it, and start it again when needed:
docker stop waves-private-node docker start waves-private-node

Configuration details

The node is configured with:

  • faster generation of blocks (10 sec interval)
  • all features pre-activated
  • custom chain id - R
  • api_key waves-private-node
  • default miner account with all Waves tokens (you can distribute these tokens to other accounts as you wish):
rich account:
    Seed text:           waves private node seed with waves tokens
    Seed:                TBXHUUcVx2n3Rgszpu5MCybRaR86JGmqCWp7XKh7czU57ox5dgjdX4K4
    Account seed:        HewBh5uTNEGLVpmDPkJoHEi5vbZ6uk7fjKdP5ghiXKBs
    Private account key: 83M4HnCQxrDMzUQqwmxfTVJPTE9WdE7zjAooZZm2jCyV
    Public account key:  AXbaBkJNocyrVpwqTzD4TpUY8fQ6eeRto9k1m2bNCzXV
    Account address:     3M4qwDomRabJKLZxuXhwfqLApQkU592nWxF

Full node configuration is available on Github in waves.custom.conf: https://github.com/wavesplatform/private-node-docker-image

Image tags

You can use the following tags:

  • latest - current version of Mainnet and Testnet
  • stagenet - current version of Stagenet
  • vX.X.X - specific version of Waves Node

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/private-node-docker-image
License: MIT license

#waves  #blockchain  #smartcontract #docker 

Docker Image with Private Custom Node for Waves Platform

How to Build The Circuit for anonymous Transactions For Waves

wasm-bellman-circuit

Here is workspace to build the circuit for anonymous transactions for waves and js bindings.

  • zwaves_primitives - crate for utils and crypto function
  • zwaves_circuit - crate for circuits
  • zwaves_wasm - crate for wasm bindings
  • js - example, how to use js bindings

First, we need to install the dependencies (cargo and npm should be already installed):

cargo install wasm-pack
cd js && npm install

To run tests

cargo test

To build

wasm-pack build zwaves_wasm

To view web page with wasm in browser.

cd js && npm run start

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/zwaves
License: MIT license

#waves  #blockchain  #smartcontract #rust 

How to Build The Circuit for anonymous Transactions For Waves

WavesCS: A C# Library for interacting with The Waves Blockchain

WavesCS

A C# library for interacting with the Waves blockchain

Supports node interaction, offline transaction signing, Matcher orders, and creating addresses and keys.

Topic on Waves Forum

Here you we can discuss library usage and further development:

https://forum.wavesplatform.com/t/wavescs-c-client-library-for-waves-api/83

Getting Started

You can install WavesPlatform.WavesCS NuGet package and add it to your project's References and in your code as:

using WavesCS;

For installation NuGet package from VS Package Manager Console you should use:

PM> Install-Package WavesPlatform.WavesCS -Version 1.1.0

For installation via UI Package Manager use this instruction.

Target framework .NET Framework 4.5.1

Documentation

The library utilizes classes to represent various Waves data structures and encoding and serialization methods:

  • WavesCS.Node
  • WavesCS.Order
  • WavesCS.OrderBook
  • WavesCS.PrivateKeyAccount
  • WavesCS.Transaction
  • WavesCS.AddressEncoding
  • WavesCS.Base58
  • WavesCS.Utils

Code Example

Code examples are in WavesCSTests project and Examples page.

Source code

[WavesCS Github repository](https://github.com/wavesplatform/WavesCS

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/WavesCS
License: MIT license

#waves  #blockchain  #smartcontract #csharp 

WavesCS: A C# Library for interacting with The Waves Blockchain

JS Library for Waves Data Services

Usage

const DataServiceClient = require('@waves/data-service-client-js').default;

// Initialization
const client = new DataServiceClient({
  rootUrl: 'http://api.wavesplatform.com/v0',
  fetch: req => window.fetch(req).then(res => res.text()), // fetch must return string
  parse: str => JSON.parse(str),
});

// Fetching
(async () => {
  const { data } = await client.getAssets('WAVES'); // data: Asset {}
})();

Methods

Response format

{ data, ...meta }

All methods do GET requests, until query is under 2k symbols, then automatically switch to POST

  • getAssets:
await client.getAssets('WAVES'); // One { data: Asset }
await client.getAssets('WAVES', '8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS'); // Or many { data: Asset[] }
await client.getAssetsByTicker('WAVES');  // Many { data: Asset[] }
await client.getAssetsByTicker('*');  // Many { data: Asset[] } - all assets
  • getPairs
const getPairs = client.getPairs('MATCHER_ID'); // set up DEX matcher
await getPairs([
  'WAVES/8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS',
  'WAVES/474jTeYx2r2Va35794tCScAXWJG9hU2HcgxzMowaZUnu'
]); // get pairs
  • getExchangeTxs:
await client.getExchangeTxs('8rEwYY4wQ4bkEkk95EiyeQnvnonX6TAnU6eiBAbVSADk'); // By id { data: Tx }
await client.getExchangeTxs({
  timeStart?: string | Date | number;
  timeEnd?: string | Date | number;
  matcher?: string;
  sender?: string;
  amountAsset?: string | Asset;
  priceAsset?: string | Asset;
  limit?: number;
  sort?: 'asc'|'desc';
}); // With filters { data: Tx[] }
await client.getExchangeTxs(); // Top 100 with default filters (timeStart = timestamp of first entry in db, timeEnd = now)
  • aliases:
const alias1 = await client.aliases.getById('@askerych');
/*
  { data: {
      address: '3P5uMgn1xvrm7g3sbUVAGLtetkNUa1AHn2M',
      alias: '@askerych'
    }
  }
  */
const alias2 = await client.aliases.getByAddress(
  '3P5uMgn1xvrm7g3sbUVAGLtetkNUa1AHn2M'
);
/*
  { data: [{
      address: '3P5uMgn1xvrm7g3sbUVAGLtetkNUa1AHn2M',
      alias: '@askerych'
    }]
  }
  */
  • getCandles:
await client.getCandles(amountAsset: string, priceAsset: string, {
  timeStart: string | Date | number;
  timeEnd?: string | Date | number;
  interval: string; // interval pattern is xy, where x - number, y - one of m (minutes), h (hours), d (days), M (Month)
});
await client.getCandles('WAVES', '8LQW8f7P5d5PZM7GtZEBgaqRPGSzS3DfPuiXrURJ4AJS', {
  timeStart: '2018-12-01',
  timeEnd: '2018-12-31',
  interval: '1d'
});

Pagination

type Response<T> = {
  data: T;
  fetchMore?: TFunction;
};
const response1 = await client.getExchangeTxs({ limit: 1, sort: 'asc' });
const data1 = response1.data;
// Process data

const response2 = await res1.fetchMore(2); // 2 more

Custom init params

You can set custom fetcher, parser and transformer for library.

type TLibOptions = {
  rootUrl: string;
  fetch?: TFunction;
  parse?: TParser;
  transform?: TFunction;
};

The path is fetch -> parse -> transform

Fetch must return string!

Fetch accepts (url, options) Fetch by default is fetch(...).then(res => res.text())

Parse by default is JSON.parse.bind(JSON) , you can use json-bigint's parse if you want to add support for bignumbers.

Transform function has next signature by default (it depends on your parse function):

({
  __type,
  data,
  ...rest
}) => any

Basically you can switch on __type and do transformations.

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/data-service-client-js
License:

#waves  #blockchain  #smartcontract 

JS Library for Waves Data Services

Waves Items: Supported on The Waves Blockchain By Convention

WAVES ITEMS

Items Protocol

The Items protocol is supported on the Waves blockchain by convention. Namely speaking it is a set of rules and transaction format restrictions. There is no specific capabilities or checks for an item format on Waves blockchain itself. Items protocol convention is a subject to change. For now it operates with version 1. Waves team will put their best efforts to provide backward compatibility is case of future changes.

Now let's take a look on how everything woks.

To represent an item on Waves blockchain you should submit two transactions with a specific format.

1. Issue transaction

The first one is issue transaction. It describes an asset - a primitive consensus entity, which will represent an item on the Waves blockchain.

Let's look at the issue transaction that follows the Waves items protocol:

{
  id: '8GyBZQjQ8GSpxvs9FWnu7MCCUzfJ45oVJQQb3ivLoA17',
  type: 3,
  version: 2,
  name: 'ITEM',
  description: '',
  quantity: 100,
  script: undefined,
  decimals: 0,
  reissuable: false,
  fee: 100000000,
  timestamp: 1562248791746,
  chainId: 84,
  senderPublicKey: '4Gqd2YuaCMh4PM6nVt33NJbETWMkJ5sHerJQCcd4Fbhe',
  proofs: ['4HkJ5TLM7HFzuiLYrY7CTyoTXcNSVs4tBiMo2Jud7be6rF14Ja9AA2qujFwhFA3WGeRw2QxvuSnc3fceMXNBJpXs']
}

This is a standard issue transaction with an extra restrictions:

  • name should be ITEM
  • description should be empty
  • script should be undefined
  • decimals should be 0
  • reissuable should be false

You can broadcast transactions to Waves blockchain via node REST API using /transactions/broadcast endpoint. You can read more about node api and play around with it using public Waves node mainnet or testnet pools.

2. Data transaction

The second transaction is Data transaction. It describes the particular in-game item and holds all the metadata that particular game will use. This data transaction must be sourced from the same account.

Here is data transaction example that should follow the issue transaction from the first section:

{
  id: 'DJadLmeQkcU4f7eGdXAqnSoKwLJbpZ3eXRMJSVcbnGT6',
  type: 12,
  version: 1,
  data: [{
      type: 'string',
      key: '8GyBZQjQ8GSpxvs9FWnu7MCCUzfJ45oVJQQb3ivLoA17',
      value: '{"version":1,"name":"The sword of pain","imageUrl":"https://i.pinimg.com/originals/02/c0/46/02c046b9ec76ebb3061515df8cb9f118.jpg","misc":{"damage":22,"power":13}}'
  }]
  fee: 100000,
  timestamp: 1562248791771,
  senderPublicKey: '4Gqd2YuaCMh4PM6nVt33NJbETWMkJ5sHerJQCcd4Fbhe',
  proofs: ['4i4e4cCvTajmSUFonzeRGhMNxHMX5S5E3jaq1fDdJ7svC74vspRm8ZPSMX3zdx7AfZ51A85HMZj6ywrENuZxTKcK'],
}

This is a standard data transaction with an extra restrictions:

  • data key should equal to issue transaction ID
  • data value should be a serialised JSON string with an Item payload object

Item payload

Item payload is an convention entity that has the following format:

{
  "version": 1,
  "name": "The sword of pain",
  "imageUrl": "https://i.pinimg.com/originals/02/c0/46/02c046b9ec76ebb3061515df8cb9f118.jpg",
  "misc": {
    "damage": 22,
    "power": 13
  }
}

It describes the item and may contain the optional misc field with the item properties.

Luckily you have no need to build and broadcast transactions yourself, instead you may use a dedicated npm-package @waves/waves-games for this.

@waves/waves-games

Installation

npm i @waves/waves-games 

Create an item

import { wavesItemsApi } from '@waves/waves-games'
const seed = 'my secret backend seed'

async function createItem() {
  const items = wavesItemsApi('T') //testnet, use 'W' for mainnet
  const item = await items
    .createItem({
      version: 1,
      quantity: 100,
      name: 'The sword of pain',
      imageUrl: 'https://i.pinimg.com/originals/02/c0/46/02c046b9ec76ebb3061515df8cb9f118.jpg',
      misc: {
        damage: 22,
        power: 13,
      },
    }).broadcast(seed)
  console.log(item)
}
createItem()

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/waves-games
License:

#waves  #blockchain  #smartcontract #typescript 

Waves Items: Supported on The Waves Blockchain By Convention

Waves Lib for Work with Big Number

bignumber

A JavaScript library for arbitrary-precision decimal and non-decimal arithmetic.

Load

The library is the single JavaScript file bignumber.umd.js (or minified, bignumber.umd.min.js).

Browser:

<script src='path/to/bignumber.js'></script>

Node.js:

$ npm install @waves/bignumber

const { BigNumber } = require('@waves/bignumber');

ES6 module:

import { BigNumber } from "@waves/bignumber"

AMD loader libraries such as requireJS:

require(['@waves/bignumber'], function(BigNumber) {
    // Use BigNumber here in local scope. No global BigNumber.
});

Use

let x = new BigNumber(123.4567);
let y = BigNumber('123456.7e-3');
let z = new BigNumber(x);
x.eq(y) && y.eq(z) && x.eq(z);      // true

To get the string value of a BigNumber use toString() or toFixed(). Using toFixed() prevents exponential notation being returned, no matter how large or small the value.

let x = new BigNumber('1111222233334444555566');
x.toString();                       // "1111222233334444555566"
x.toFixed();                        // "1111222233334444555566"

Clone

Клонирует объект

const some = new BigNumber(1);
const clone = some.clone();

Add

Выполняет сложение

const bigNum = new BigNumber('100');
const result = bigNum.add('50'); // with method toFixed '150'

Sub

Вычитание

const bigNum = new BigNumber('100');
const result = bigNum.sub('50'); // with method toFixed '50'

Mul

Умножение

const bigNum = new BigNumber('100');
const result = bigNum.mul(2); // with method toFixed '200'

Div

Деление

const bigNum = new BigNumber('100');
const result = bigNum.div(2); //  with method toFixed '50'

Pow

Возведение в степень

const bigNum = new BigNumber('100');
const result = bigNum.pow(2); // with method toFixed '10000'

Sqrt

Квадратный корень

const bigNum = new BigNumber('100');
const result = bigNum.sqrt(); // with method toFixed '10'

Abs

Модуль

const bigNum = new BigNumber('-100');
const result = bigNum.abs(); // with method toFixed 100

Mod

Остаток от деления

const bigNum = new BigNumber('100');
const result = bigNum.mod(10); // with method toFixed '0' 

RoundTo

Округляет. Принимает количество знаков после запятой после округлени и режим округления см тут: http://mikemcl.github.io/bignumber.js/#constructor-properties

const bigNum = new BigNumber('100');
const result = bigNum.roundTo(); //

Eq

Равенство

const bigNum = new BigNumber('100');
const result = bigNum.eq(100); // true

Lt

Меньше

const bigNum = new BigNumber('100');
const result = bigNum.lt(); //

Gt

Больше

const bigNum = new BigNumber('100');
const result = bigNum.gt(); //

Lte

Меньше или равно

const bigNum = new BigNumber('100');
const result = bigNum.lte(); //

Gte

Больше или равно

const bigNum = new BigNumber('100');
const result = bigNum.gte(); //

IsNaN

Проверяет на NaN

const bigNum = new BigNumber('100');
const result = bigNum.isNaN(); // false

IsFinite

Проверяет на Infinity (положительный и отрицательный)

const bigNum = new BigNumber('100');
const result = bigNum.isFinite(); //

IsZero

Проверяет на равенство нулю

const bigNum = new BigNumber('100');
const result = bigNum.isZero(); // false

IsPositive

Больше нуля

const bigNum = new BigNumber('100');
const result = bigNum.isPositive(); // true

IsNegative

Меньше нуля

const bigNum = new BigNumber('100');
const result = bigNum.isNegative(); // false

IsInt

Проверяет целое ли число

const bigNum = new BigNumber('100');
const result = bigNum.isInt(); //

GetDecimalsCount

Получаем количество занков после запятой у числа

const bigNum = new BigNumber('100');
const result = bigNum.getDecimalsCount(); // 0

IsEven

Четное

const bigNum = new BigNumber('100');
const result = bigNum.isEven(); // true

IsOdd

Не чётное

const bigNum = new BigNumber('100');
const result = bigNum.isOdd(); // false

ToBytes

Переводим число в байты со знаком (8 байт). Работает только с целыми числами.

const bigNum = new BigNumber('100');
const result = bigNum.toBytes();

ToFormat

Выводим число в строковом эквиваленте c с учётом настроек форматирования. Опционально принимает количество знаков округления, режим округления (как в roundTo) и настройки формата вывода.

const bigNum = new BigNumber('1000000.12312');
bigNum.toFormat(); // 1,000,000.12312 
bigNum.toFormat(2); // 1,000,000.12 
bigNum.toFormat(2); // 1,000,000.12 
bigNum.toFormat(2, 0); // 1,000,000.13 
bigNum.toFormat(2, 0, { groupSeparator: ' ' }); // 1 000 000.13 

ToFixed

Выводим число в строковом эквиваленте. Опционально принимает количество знаков округления и режим округления (как в roundTo)

const bigNum = new BigNumber('100');
const result = bigNum.toFixed(); //

ToNumber

Приводит к числу

const bigNum = new BigNumber('100');
const result = bigNum.toNumber(); //

Static Methods

fromBytes

Выводит знаковое число из байт. Работает только с 8 байтами.

const some = BigNumber.fromBytes(Uint8Array.from([1,2,3,4,5,6,7,8]));

max

Принимает любое количество аргументов, выбирает наибольшее число из аргументов

BigNumber.max(1, '2', new BigNumber(4)); // with method toFixed '4'

min

Принимает любое количество аргументов, выбирает наименьшее число из аргументов

BigNumber.min(1, '2', new BigNumber(4)); // with method toFixed '1'

sum

Принимает любое количество аргументов, складывает числа

BigNumber.min(1, '2', new BigNumber(4)); //with method toFixed '7'

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/bignumber
License:

#waves  #blockchain  #smartcontract #typescript 

Waves Lib for Work with Big Number

Demo Bot for Scalping Strategy on Waves Based DEXes

SimpleBot

SimpleBot is a Python bot implementing a scalping trading strategy. It can work with any assets pair on the Waves DEX.

SimpleBot exploits small changes in currency prices: it buys at the mean price minus some step and sells at the mean price plus some step, in order to gain the bid/ask difference. It normally involves establishing and liquidating a position quickly, in this case within 15 seconds.

The SimpleBot with initial parameters trade on Waves-BTC pair (Waves is an amount asset and BTC is a price_asset). The spread mean price is (best_bid + best_ask) / 2. The price step is 0.5% from mean price. The SimpleBot place the buy order at price meanprice * (1 - price_step) and the amount (BTC_balance / bid_price) - order_fee. The sell order is placed at meanprice * (1 + price_step) and the amount equal to Waves_balance - order_fee.

Installation

SimpleBot requires Python 3.x and the following Python packages:

You can install them with

pip install pywaves
pip install configparser 

Getting Started

You can start SimpleBot with this command:

python SimpleBot.py config.cfg

Configuration

Configuration file config.cfg have next set of parameters: node is the address of the fullnode

matcher is the matcher address

chain mainnet or testnet

order_fee is the fee to place buy and sell orders

order_lifetime is the maximum life time (in seconds) for an open order

private_key is the private key of the trading account

amount_asset and price_asset are the IDs of the traded assets pair

price_step is the step of scalping relative to the mean price (proportion)

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/demo-python-trading-bot
License:

#waves  #blockchain  #smartcontract 

Demo Bot for Scalping Strategy on Waves Based DEXes

Waves Wallet IOS App using Swift

Waves Wallet on iOS

Waves Wallet iOS app is the official wallet software designed with mass adoption in mind. It allows to access your Waves account, handle financial operations, and trade on DEX.

Blockchain for the people

Keep up with the latest news and articles, and find out all about events happening on the Waves Platform.

Demo

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/WavesWallet-iOS
License: MIT license

#waves  #blockchains  #smartcontract #swift 

Waves Wallet IOS App using Swift

Waves Rest: Create and Sign Transactions for Waves Blockchain

waves-transactions

Using this library you can easily create and sign transactions for Waves blockchain. It also allows you to multi-sign existing transactions or create them without signature at all.

Check full documentation on GitHub Pages.

Transactions

The idea is really simple - you create transaction and sign it from a minimal set of required params. If you want to create Transfer transaction the minimum you need to provide is amount and recipient as defined in Transfer params:


const { transfer } = require('@waves/waves-transactions')
const seed = 'some example seed phrase'
const signedTranserTx = transfer({ 
  amount: 1,
  recipient: '3P6fVra21KmTfWHBdib45iYV6aFduh4WwC2',
  timestamp: 1536917842558, //Timestamp is optional but it was overrided, in case timestamp is not provided it will fallback to Date.now()

  //Every function from the list above has a set of required and optional params
  //senderPublicKey: 'Cq5itmx4wbYuogySAoUp58MimLLkQrFFLr1tpJy2BYp1', // By default it is derived from seed, 
  // but if you don't want to sign transaction you have to provide it
  //fee: 100000, //Fee is always optional, in case fee is not provided, it will be calculated for you
  //additionalFee: 400000, //If fee is not set, this value will be added to the auto calculated value
  //feeAssetId: undefined
}, seed)

Output will be a signed transfer transaction:

{
  id: '8NrUwgKRCMFbUbqXKQAHkGnspmWHEjKUSi5opEC6Havq',
  type: 4,
  version: 2,
  recipient: '3P6fVra21KmTfWHBdib45iYV6aFduh4WwC2',
  attachment: undefined,
  feeAssetId: undefined,
  assetId: undefined,
  amount: 1,
  fee: 100000,
  senderPublicKey: '6nR7CXVV7Zmt9ew11BsNzSvVmuyM5PF6VPbWHW9BHgPq',
  timestamp: 1536917842558,
  proofs: [
    '25kyX6HGjS3rkPTJRj5NVH6LLuZe6SzCzFtoJ8GDkojY9U5oPfVrnwBgrCHXZicfsmLthPUjTrfT9TQL2ciYrPGE'
  ]
}

Now you are able to POST it to Waves API or store for future purpose or you can add another signature from other party:

const otherPartySeed = 'other party seed phrase'
const transferSidnedWithTwoParties = transfer(signedTranserTx, seed)

So now there are two proofs:

{
  id: '8NrUwgKRCMFbUbqXKQAHkGnspmWHEjKUSi5opEC6Havq',
  type: 4,
  version: 2,
  recipient: '3P6fVra21KmTfWHBdib45iYV6aFduh4WwC2',
  attachment: undefined,
  feeAssetId: undefined,
  assetId: undefined,
  amount: 1,
  fee: 100000,
  senderPublicKey: '6nR7CXVV7Zmt9ew11BsNzSvVmuyM5PF6VPbWHW9BHgPq',
  timestamp: 1536917842558,
  proofs: [
    '25kyX6HGjS3rkPTJRj5NVH6LLuZe6SzCzFtoJ8GDkojY9U5oPfVrnwBgrCHXZicfsmLthPUjTrfT9TQL2ciYrPGE',
    'CM9emPzpe6Ram7ZxcYax6s7Hkw6698wXCMPSckveFAS2Yh9vqJpy1X9nL7p4RKgU3UEa8c9RGXfUK6mFFq4dL9z'
  ]
}

Download Details:
Author: wavesplatform
Source Code: https://github.com/wavesplatform/waves-rest
License:

#waves  #blockchain  #smartcontract 

Waves Rest: Create and Sign Transactions for Waves Blockchain