diff --git a/doc/ApolloWebCryptotypescriptlibrary..html b/doc/ApolloWebCryptotypescriptlibrary..html new file mode 100644 index 0000000..3b7e446 --- /dev/null +++ b/doc/ApolloWebCryptotypescriptlibrary..html @@ -0,0 +1 @@ +

Apollo Web Crypto typescript library

Introduction

Apollo web crypto library is used for offline transaction processing - create and sign transactions with no secretPhrase or secret key disclosing in communication with Apollo Blockchain node.

Quick Start Guide

Installation

First, You need to install the apl-web-crypto nodejs package.

npm install apl-web-crypto

Second, we need to configure the Apollo Node we have to use.

Apollo web crypto uses dotenv module for configuration:

Project setup

Create a .env file at the root of the project add the following line into it.

APL_SERVER=https://wallet.test.apollowallet.org

Then we will create an example JavaScript file, simpleTransactionSign.js

Add following lines into simpleTransactionSign.js file 

import { Transaction } from "apl-web-crypto";
require("dotenv").config()

Transaction creation

To create transactions in Apollo, we have to add to transaction data several fields. In this document, we will use sendMoney transaction. For sendMoney, we have to fill following fields: amountATM, deadline, recipient, feeATM. One of publicKey or secretPhrase. For offline signing, we do not want to disclose our secretPhrase, so we will fill publicKey. It has to be sender’s publicKey

// Apollo has 8 decimals
const ONE_APL = 100000000;
const data = {
         requestType:
'sendMoney',
        publicKey:
"24a88cc13c9a3a9f06c636b58c5b607fcb7cff14d449325691fa448933e6b870",
         amountATM:
2 * ONE_APL,
         feeATM: ONE_APL,
         deadline:
60,
         recipient:
"APL-RQTU-56W2-AAMY-7MTLB"
        };

Get not signed transaction bytes

At first, we can get Transaction Bytes from the server, and then we will perform offline signing. Note, that this way we can get Transaction Bytes for any transaction type.

// function notSign used to get transaction bytes without
// signing
async function getNotSignedData(data)
{
        
const result = await Transaction.sendNotSign(data);
        
return result;
}

let unsignedTransactionData = getNotSignedData(data)
.then(unsignedResponse => {
        
/* process unsigned transaction here */
        
console.log(unsignedResponse);
}).catch();

This way we will get unsigned transaction data from the server.

Sign transaction

To sign transaction we have to add sign function:

async function sign(secretPhrase, unsignedResponse)
{
        
const sendData =  {secretPhrase: secretPhrase };
        
const result = await Transaction.processOfflineSign(sendData, unsignedResponse);
        
return result;
}

Then, we can modify the code, to add transaction signing, and processing (broadcast):

getNotSignedData(data)
.then(unsignedResponse => {
        
/* process unsigned transaction here */

      console.log(unsignedResponse);
        sign(
"10", unsignedResponse).then(signedBytes => {
               
/* process signed transaction here */

          console.log(signedBytes);
        }).catch();

}).catch();

diff --git a/doc/Apollowalletstypes.html b/doc/Apollowalletstypes.html new file mode 100644 index 0000000..24f023b --- /dev/null +++ b/doc/Apollowalletstypes.html @@ -0,0 +1 @@ +

Introduction

This document purpose is to explain difference between Apollo wallets types, wallet mechanics and transaction signing principles

Standard Wallet

How to create a Standard Wallet?

  1. Pick a random secret phrase.

A secret phrase can be generated by any random character sequence generator. Secret phrase should be long enough to avoid access from third-parties.

  1. To get WalletID send getAccountID http request to apollo API. If secret Phrase contains spaces, replace them with “+” sign:

Request:

curl -X GET “http://localhost:7876/apl?requestType=getAccountId&secretPhrase=random+Custom+Secret+Phrase”

Response:

{"accountRS":"APL-37Q4-VWXA-BPX8-8DKFR","publicKey":"ba989e4265765ae749c45e4c62ccf52a907ee3427932fc7e0bcd898c7f62dc2b","requestProcessingTime":1,"account":"7761439245578835650"}

WalletID is in the “accountRS” field. Also, API returns public key and account number.

Transaction signing

When calling a signTransaction API request, You have to fill the secretPhrase field.

Offline signing library can be used for Standard Wallets

You can use standard Wallet on ANY Apollo node

Wallet mechanics

secretPhrase and walletID are mathematically connected:

Vault Wallet

How to create a Vault Wallet?

  1. Call generateAccount API call (You can also use custom passphrase)

Request:

curl -X POST “http://localhost:7876/apl?requestType=generateAccount

Response (example):

  1. To get WalletID send getAccountID http request to apollo API. If secret Phrase contains spaces, replace them with “+” sign:

Request:

curl -X GET “http://localhost:7876/apl?requestType=getAccountId&secretPhrase=random+Custom+Secret+Phrase”

Response (example):

{

    "requestProcessingTime": 5,

    "account": "6921607032493309014",

    "accountRS": "APL-RZ4Q-XKZB-WMP7-8WM52",

    "publicKey": "7aac678c421d9295b465438d2790abd5f84d800be9d5f12bd6baa2d6aeff630a",

    "passphrase": "couch engraved eloquent dossier downtime ointment ducked spurn pashas jujitsu jingles shirring bummers homework",

    "apl": {

        "currency": "apl",

        "wallets": {

            "account": "6921607032493309014",

            "accountRS": "APL-RZ4Q-XKZB-WMP7-8WM52",

            "publicKey": "7aac678c421d9295b465438d2790abd5f84d800be9d5f12bd6baa2d6aeff630a",

            "passphrase": "couch engraved eloquent dossier downtime ointment ducked spurn pashas jujitsu jingles shirring bummers homework"

        }

    },

    "eth": [

        {

            "address": "0x9908c5cb7f47c1022867cb52b6c5dddd30ee59e4",

            "publicKey": "f32f803698e53efaf502a098439cc4167a299901f0b58657faaa9a84e9d3d8a76d9b47416ce48b7ac4ccad3eaaf31b05209bb32fde69c0fcb8f7f0fa8802e2dc"

        }

    ]

}

API returns wallet id and passphrase. Do not be confused with secretPhrase.

Transaction signing

When calling a signTransaction API request, You have to fill the passphrase and sender fields. (not secretPhrase)

Offline signing library can not be used for Vault  Wallets

You can use Vault Wallet only on the node, where the wallet was created

Wallet mechanics

  1. When user creates VaultWallet, a random secretKey is generated.
  2. secretKey is stored in Vault Wallet file, encrypted by passphrase.
  3.  passphrase and accountID  are NOT mathematically connected
  4. secretKey and walletID are mathematically connected:
  5. passphrase is used to decrypt Vault Wallet file on the node. Only after correct decryption seretKey can be used for transaction signing, server-side only.

Simple Vault Wallet creation:

        How Vault Wallet works:

\ No newline at end of file diff --git a/doc/examples/.env.skel b/doc/examples/.env.skel new file mode 100644 index 0000000..d3c2562 --- /dev/null +++ b/doc/examples/.env.skel @@ -0,0 +1 @@ +APL_SERVER=http://localhost:7876 \ No newline at end of file diff --git a/doc/examples/package.json b/doc/examples/package.json new file mode 100644 index 0000000..e02d435 --- /dev/null +++ b/doc/examples/package.json @@ -0,0 +1,27 @@ +{ + "name": "SignTransactionSample", + "version": "1.0.0", + "description": "Sign transaction sample", + "main": "server.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "start": "node signTransaction.js" + }, + "repository": { + "type": "git", + "url": "git+https://firstb@bitbucket.org/firstbridge_company/apollo-faucet.git" + }, + "author": "Rostyslav Golda", + "license": "GPL-2.0-or-later", + "homepage": "https://bitbucket.org/firstbridge_company/apollo-faucet#readme", + "dependencies": { + "apl-web-crypto": "^1.0.0", + "request": "^2.88.2", + "sqlite3": "^4.0.8", + "typescript": "^4.4.3" + }, + "devDependencies": { + "@types/node": "^16.9.4", + "dotenv": "^10.0.0" + } +} diff --git a/doc/examples/signAndSendTransaction.js b/doc/examples/signAndSendTransaction.js new file mode 100644 index 0000000..cf76da4 --- /dev/null +++ b/doc/examples/signAndSendTransaction.js @@ -0,0 +1,29 @@ +const { Crypto, Transaction } = require('apl-web-crypto'); +require('dotenv').config(); + +(async () => { + // Apollo has 8 decimals + const ONE_APL = 100000000; + const secretPhrase = '10'; + const publicKey = Crypto.getPublicKey(secretPhrase); + const data = { + requestType: 'sendMoney', + publicKey, + amountATM: 2 * ONE_APL, + feeATM: ONE_APL, + deadline: 60, + recipient: "APL-RQTU-56W2-AAMY-7MTLB", + secretPhrase + }; + + const signAndSend = async (dataObj) => { + return await Transaction.sendWithOfflineSign(dataObj); + } + + try { + const serverResponse = await signAndSend(data) + console.log(serverResponse); + } catch (e) { + console.log(e); + } +})(); diff --git a/doc/examples/signTransaction.js b/doc/examples/signTransaction.js new file mode 100644 index 0000000..09134c9 --- /dev/null +++ b/doc/examples/signTransaction.js @@ -0,0 +1,39 @@ +const { Crypto, Transaction } = require('apl-web-crypto'); +require('dotenv').config(); + +(async () => { + // Apollo has 8 decimals + const ONE_APL = 100000000; + const secretPhrase = '10'; + const publicKey = Crypto.getPublicKey(secretPhrase); + const data = { + requestType: 'sendMoney', + publicKey, + amountATM: 2 * ONE_APL, + feeATM: ONE_APL, + deadline: 60, + recipient: 'APL-RQTU-56W2-AAMY-7MTLB', + }; + + // function notSign used to get transaction bytes without signing + const getNotSignedData = async (dataObj) => { + return await Transaction.sendNotSign(dataObj); + }; + + const sign = async (secretPhrase, unsignedResponse) => { + const sendData = { secretPhrase }; + return await Transaction.processOfflineSign(sendData, unsignedResponse); + }; + + try { + // process unsigned transaction here + const unsignedResponse = await getNotSignedData(data); + console.log(unsignedResponse); + + // process signed transaction here + const signedBytes = await sign(secretPhrase, unsignedResponse); + console.log(signedBytes); + } catch (e) { + console.log(e); + } +})(); diff --git a/doc/images/image1.png b/doc/images/image1.png new file mode 100644 index 0000000..05f3039 Binary files /dev/null and b/doc/images/image1.png differ diff --git a/doc/images/image2.png b/doc/images/image2.png new file mode 100644 index 0000000..632f33f Binary files /dev/null and b/doc/images/image2.png differ diff --git a/doc/images/image3.png b/doc/images/image3.png new file mode 100644 index 0000000..de514ee Binary files /dev/null and b/doc/images/image3.png differ