From 644dcfb7fdcbbe9ef561bf0abf2d5d4ba766e8a9 Mon Sep 17 00:00:00 2001 From: Rostyslav Golda Date: Mon, 11 Oct 2021 09:55:56 +0300 Subject: [PATCH 1/4] Added some docs --- doc/ApolloWebCryptotypescriptlibrary..html | 1 + doc/Apollowalletstypes.html | 1 + doc/expamples/signTransaction.ts | 42 +++++++++++++++++++++ doc/images/image1.png | Bin 0 -> 8218 bytes doc/images/image2.png | Bin 0 -> 22524 bytes doc/images/image3.png | Bin 0 -> 15550 bytes 6 files changed, 44 insertions(+) create mode 100644 doc/ApolloWebCryptotypescriptlibrary..html create mode 100644 doc/Apollowalletstypes.html create mode 100644 doc/expamples/signTransaction.ts create mode 100644 doc/images/image1.png create mode 100644 doc/images/image2.png create mode 100644 doc/images/image3.png diff --git a/doc/ApolloWebCryptotypescriptlibrary..html b/doc/ApolloWebCryptotypescriptlibrary..html new file mode 100644 index 0000000..f41bcfe --- /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 TypeScript file, simpleTransactionSign.ts

Add following lines into simpleTransactionSign.ts 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 ou8r 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();

\ No newline at end of file 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/expamples/signTransaction.ts b/doc/expamples/signTransaction.ts new file mode 100644 index 0000000..db422a8 --- /dev/null +++ b/doc/expamples/signTransaction.ts @@ -0,0 +1,42 @@ +import { Transaction } from "apl-web-crypto"; +require("dotenv").config() + +const ONE_APL = 100000000; +const data = { + requestType: 'sendMoney', +// publicKey: '39dc2e813bb45ff063a376e316b10cd0addd7306555ca0dd2890194d37960152', + publicKey: "24a88cc13c9a3a9f06c636b58c5b607fcb7cff14d449325691fa448933e6b870", + amountATM: 2 * ONE_APL, + feeATM: ONE_APL, + deadline: 60, + recipient: "APL-RQTU-56W2-AAMY-7MTLB" + }; + +async function notSign(data) +{ + const result = await Transaction.sendNotSign(data); + return result; +} + +async function sign(secretPhrase, unsignedResponse) +{ + const sendData = {secretPhrase: secretPhrase }; + const result = await Transaction.processOfflineSign(sendData, unsignedResponse); + return result; +} + +async function broadcast(signedResponse) +{ + await Transaction.send(signedResponse); +} + +let unsignedTransactionData = notSign(data) +.then(unsignedResponse => { + console.log(unsignedResponse); + sign("10", unsignedResponse).then(signedBytes => { + console.log(signedBytes); + }).catch(); + + +}) +.catch(); diff --git a/doc/images/image1.png b/doc/images/image1.png new file mode 100644 index 0000000000000000000000000000000000000000..05f3039ecf1bd9ab77e0a3b527532f0b38576b41 GIT binary patch literal 8218 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 literal 0 HcmV?d00001 diff --git a/doc/images/image2.png b/doc/images/image2.png new file mode 100644 index 0000000000000000000000000000000000000000..632f33f25c0f306b9b30466f90d7c000d9ada94c GIT binary patch literal 22524 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

Wed&uJsDxbwE+iM3Q~<-oPdJAqF8=j3dn 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 literal 0 HcmV?d00001 diff --git a/doc/images/image3.png b/doc/images/image3.png new file mode 100644 index 0000000000000000000000000000000000000000..de514ee42d625ad7fcca99a53ab116312465ef56 GIT binary patch literal 15550 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 literal 0 HcmV?d00001 From abd6acd44435e167408247e180f3ab9ac70006e5 Mon Sep 17 00:00:00 2001 From: Rostyslav Golda Date: Tue, 12 Oct 2021 09:57:33 +0300 Subject: [PATCH 2/4] Added doc and examples --- doc/expamples/package.json | 27 +++++++++++++++++++++++++ doc/expamples/signAndSendTransaction.ts | 25 +++++++++++++++++++++++ 2 files changed, 52 insertions(+) create mode 100644 doc/expamples/package.json create mode 100644 doc/expamples/signAndSendTransaction.ts diff --git a/doc/expamples/package.json b/doc/expamples/package.json new file mode 100644 index 0000000..e02d435 --- /dev/null +++ b/doc/expamples/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/expamples/signAndSendTransaction.ts b/doc/expamples/signAndSendTransaction.ts new file mode 100644 index 0000000..d48ea20 --- /dev/null +++ b/doc/expamples/signAndSendTransaction.ts @@ -0,0 +1,25 @@ +import { Transaction } from "apl-web-crypto"; +require("dotenv").config() + +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", + secretPhrase: '10' + }; + +async function signAndSend(data) +{ + const result = await Transaction.sendWithOfflineSign(data); + return result; +} + +let serverResponse = signAndSend(data) +.then(response => { + console.log(response); +}) +.catch(); From a377675478ef63be3c9df85b391b2ef77cbde308 Mon Sep 17 00:00:00 2001 From: Rostyslav Golda Date: Tue, 19 Oct 2021 16:57:58 +0300 Subject: [PATCH 3/4] Prettyfied the code, renamed examples directory --- doc/{expamples => examples}/package.json | 0 .../signAndSendTransaction.ts | 0 doc/examples/signTransaction.ts | 40 ++++++++++++++++++ doc/expamples/signTransaction.ts | 42 ------------------- 4 files changed, 40 insertions(+), 42 deletions(-) rename doc/{expamples => examples}/package.json (100%) rename doc/{expamples => examples}/signAndSendTransaction.ts (100%) create mode 100644 doc/examples/signTransaction.ts delete mode 100644 doc/expamples/signTransaction.ts diff --git a/doc/expamples/package.json b/doc/examples/package.json similarity index 100% rename from doc/expamples/package.json rename to doc/examples/package.json diff --git a/doc/expamples/signAndSendTransaction.ts b/doc/examples/signAndSendTransaction.ts similarity index 100% rename from doc/expamples/signAndSendTransaction.ts rename to doc/examples/signAndSendTransaction.ts diff --git a/doc/examples/signTransaction.ts b/doc/examples/signTransaction.ts new file mode 100644 index 0000000..cb7fe9e --- /dev/null +++ b/doc/examples/signTransaction.ts @@ -0,0 +1,40 @@ +import { Transaction } from "apl-web-crypto"; +require("dotenv").config(); + +(async () => { + 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" + }; + + // function getNotSignedData used to get transaction bytes without signing + const getNotSignedData = async (dataObj) => + { + return await Transaction.sendNotSign(dataObj); + } + + const sign = async (secretPhrase, unsignedResponse) => + { + const result = await Transaction.processOfflineSign(secretPhrase, unsignedResponse); + return result; + } + + try { + const unsignedResponse = await getNotSignedData(data); + // process unsigned transaction here + console.log(unsignedResponse); + + // Here is the sample secretPhrase. Should be the working secretPhrase + const secretPhrase = '10'; + const signedBytes = await sign(secretPhrase, unsignedResponse) + // process signed transaction here + console.log(signedBytes); + } catch (e) { + console.log(e); + } +})(); \ No newline at end of file diff --git a/doc/expamples/signTransaction.ts b/doc/expamples/signTransaction.ts deleted file mode 100644 index db422a8..0000000 --- a/doc/expamples/signTransaction.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { Transaction } from "apl-web-crypto"; -require("dotenv").config() - -const ONE_APL = 100000000; -const data = { - requestType: 'sendMoney', -// publicKey: '39dc2e813bb45ff063a376e316b10cd0addd7306555ca0dd2890194d37960152', - publicKey: "24a88cc13c9a3a9f06c636b58c5b607fcb7cff14d449325691fa448933e6b870", - amountATM: 2 * ONE_APL, - feeATM: ONE_APL, - deadline: 60, - recipient: "APL-RQTU-56W2-AAMY-7MTLB" - }; - -async function notSign(data) -{ - const result = await Transaction.sendNotSign(data); - return result; -} - -async function sign(secretPhrase, unsignedResponse) -{ - const sendData = {secretPhrase: secretPhrase }; - const result = await Transaction.processOfflineSign(sendData, unsignedResponse); - return result; -} - -async function broadcast(signedResponse) -{ - await Transaction.send(signedResponse); -} - -let unsignedTransactionData = notSign(data) -.then(unsignedResponse => { - console.log(unsignedResponse); - sign("10", unsignedResponse).then(signedBytes => { - console.log(signedBytes); - }).catch(); - - -}) -.catch(); From f4469bd69082be163c23b4eb7a9817c83ca91871 Mon Sep 17 00:00:00 2001 From: Ellina Kolisnichenko Date: Tue, 19 Oct 2021 17:49:37 +0300 Subject: [PATCH 4/4] Change signAndSendTransaction --- doc/ApolloWebCryptotypescriptlibrary..html | 2 +- doc/examples/.env.skel | 1 + doc/examples/signAndSendTransaction.js | 29 ++++++++++++++++ doc/examples/signAndSendTransaction.ts | 25 -------------- doc/examples/signTransaction.js | 39 +++++++++++++++++++++ doc/examples/signTransaction.ts | 40 ---------------------- 6 files changed, 70 insertions(+), 66 deletions(-) create mode 100644 doc/examples/.env.skel create mode 100644 doc/examples/signAndSendTransaction.js delete mode 100644 doc/examples/signAndSendTransaction.ts create mode 100644 doc/examples/signTransaction.js delete mode 100644 doc/examples/signTransaction.ts diff --git a/doc/ApolloWebCryptotypescriptlibrary..html b/doc/ApolloWebCryptotypescriptlibrary..html index f41bcfe..3b7e446 100644 --- a/doc/ApolloWebCryptotypescriptlibrary..html +++ b/doc/ApolloWebCryptotypescriptlibrary..html @@ -1 +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 TypeScript file, simpleTransactionSign.ts

Add following lines into simpleTransactionSign.ts 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 ou8r 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();

\ No newline at end of file +

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/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/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/signAndSendTransaction.ts b/doc/examples/signAndSendTransaction.ts deleted file mode 100644 index d48ea20..0000000 --- a/doc/examples/signAndSendTransaction.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Transaction } from "apl-web-crypto"; -require("dotenv").config() - -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", - secretPhrase: '10' - }; - -async function signAndSend(data) -{ - const result = await Transaction.sendWithOfflineSign(data); - return result; -} - -let serverResponse = signAndSend(data) -.then(response => { - console.log(response); -}) -.catch(); 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/examples/signTransaction.ts b/doc/examples/signTransaction.ts deleted file mode 100644 index cb7fe9e..0000000 --- a/doc/examples/signTransaction.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Transaction } from "apl-web-crypto"; -require("dotenv").config(); - -(async () => { - 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" - }; - - // function getNotSignedData used to get transaction bytes without signing - const getNotSignedData = async (dataObj) => - { - return await Transaction.sendNotSign(dataObj); - } - - const sign = async (secretPhrase, unsignedResponse) => - { - const result = await Transaction.processOfflineSign(secretPhrase, unsignedResponse); - return result; - } - - try { - const unsignedResponse = await getNotSignedData(data); - // process unsigned transaction here - console.log(unsignedResponse); - - // Here is the sample secretPhrase. Should be the working secretPhrase - const secretPhrase = '10'; - const signedBytes = await sign(secretPhrase, unsignedResponse) - // process signed transaction here - console.log(signedBytes); - } catch (e) { - console.log(e); - } -})(); \ No newline at end of file