Initial commit

This commit is contained in:
AlphaX-Projects
2021-12-25 14:39:47 +01:00
commit 2f823927a5
3687 changed files with 37381 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
/*
Copyright 2017-2018 @ irontiga and vbcs (original developer)
*/
'use strict';
import Base58 from './deps/Base58.js'
import { Sha256, Sha512 } from 'asmcrypto.js'
import nacl from './deps/nacl-fast.js'
import utils from './deps/utils.js'
import { generateSaveWalletData } from './storeWallet.js'
import publicKeyToAddress from './wallet/publicKeyToAddress.js'
import AltcoinHDWallet from "./bitcoin/AltcoinHDWallet";
export default class PhraseWallet {
constructor(seed, walletVersion) {
this._walletVersion = walletVersion || 2
this.seed = seed
this.savedSeedData = {}
this.hasBeenSaved = false
}
set seed(seed) {
this._byteSeed = seed
this._base58Seed = Base58.encode(seed)
this._addresses = []
this.genAddress(0)
}
getAddress(nonce) {
return this._addresses[nonce]
}
get addresses() {
return this._addresses
}
get addressIDs() {
return this._addresses.map(addr => {
return addr.address
})
}
get seed() {
return this._byteSeed
}
addressExists(nonce) {
return this._addresses[nonce] != undefined
}
_genAddressSeed(seed) {
let newSeed = new Sha512().process(seed).finish().result
newSeed = new Sha512().process(utils.appendBuffer(newSeed, seed)).finish().result
return newSeed
}
genAddress(nonce) {
if (nonce >= this._addresses.length) {
this._addresses.length = nonce + 1
}
if (this.addressExists(nonce)) {
return this.addresses[nonce]
}
const nonceBytes = utils.int32ToBytes(nonce)
let addrSeed = new Uint8Array()
addrSeed = utils.appendBuffer(addrSeed, nonceBytes)
addrSeed = utils.appendBuffer(addrSeed, this._byteSeed)
addrSeed = utils.appendBuffer(addrSeed, nonceBytes)
if (this._walletVersion == 1) {
addrSeed = new Sha256().process(
new Sha256()
.process(addrSeed)
.finish()
.result
).finish().result
addrSeed = this._byteSeed
} else {
addrSeed = this._genAddressSeed(addrSeed).slice(0, 32)
}
const addrKeyPair = nacl.sign.keyPair.fromSeed(new Uint8Array(addrSeed));
const address = publicKeyToAddress(addrKeyPair.publicKey);
const qoraAddress = publicKeyToAddress(addrKeyPair.publicKey, true);
// Create Bitcoin HD Wallet
const btcSeed = [...addrSeed];
const btcWallet = new AltcoinHDWallet({
mainnet: {
private: 0x0488ADE4,
public: 0x0488B21E,
prefix: 0
},
testnet: {
private: 0x04358394,
public: 0x043587CF,
prefix: 0x6F
}
}).createWallet(new Uint8Array(btcSeed), false);
// Create Litecoin HD Wallet
const ltcSeed = [...addrSeed];
const ltcWallet = new AltcoinHDWallet({
mainnet: {
private: 0x0488ADE4,
public: 0x0488B21E,
prefix: 0x30
},
testnet: {
private: 0x04358394,
public: 0x043587CF,
prefix: 0x6F
}
}).createWallet(new Uint8Array(ltcSeed), false, 'LTC');
// Create Dogecoin HD Wallet
const dogeSeed = [...addrSeed];
const dogeWallet = new AltcoinHDWallet({
mainnet: {
private: 0x02FAC398,
public: 0x02FACAFD,
prefix: 0x1E
},
testnet: {
private: 0x04358394,
public: 0x043587CF,
prefix: 0x71
}
}).createWallet(new Uint8Array(dogeSeed), false, 'DOGE');
this._addresses[nonce] = {
address,
btcWallet,
ltcWallet,
dogeWallet,
qoraAddress,
keyPair: {
publicKey: addrKeyPair.publicKey,
privateKey: addrKeyPair.secretKey
},
base58PublicKey: Base58.encode(addrKeyPair.publicKey),
seed: addrSeed,
nonce: nonce
}
return this._addresses[nonce]
}
generateSaveWalletData(...args) {
return generateSaveWalletData(this, ...args)
}
}

View File

@@ -0,0 +1,9 @@
export { request } from './fetch-request.js'
export { transactionTypes as transactions } from './transactions/transactions.js'
export { processTransaction, createTransaction, computeChatNonce, signChatTransaction } from './createTransaction.js'
export { tradeBotCreateRequest, tradeBotRespondRequest, signTradeBotTxn, deleteTradeOffer, sendBtc, sendLtc, sendDoge } from './tradeRequest.js'
export { cancelAllOffers } from './transactions/trade-portal/tradeoffer/cancelAllOffers.js'

View File

@@ -0,0 +1,873 @@
'use strict';
import Base58 from '../deps/Base58.js'
import { Sha256, Sha512 } from 'asmcrypto.js'
import jsSHA from "jssha";
import RIPEMD160 from '../deps/ripemd160.js'
import utils from '../deps/utils.js'
import { EllipticCurve, BigInteger } from './ecbn.js';
export default class AltcoinHDWallet {
constructor(addressParams) {
/**
* Seed - 32 bytes
*/
this.seed = new Uint8Array(32)
/**
* Version Bytes - 4 byte
*/
this.versionBytes = addressParams
/**
* Depth - 1 byte
*/
this.depth = 0
/**
* Parent Fingerprint - 4 bytes
*/
this.parentFingerprint = '0x00000000' // master key
/**
* Child Index - 4 bytes
*/
this.childIndex = '0x00000000' // master key
/**
* Chain Code - 32 bytes
*/
this.chainCode = new Uint8Array(32)
/**
* Key Data - 33 bytes
*/
this.keyData = new Uint8Array(33)
/**
* Seed Hash - 64 bytes
*/
this.seedHash = new Uint8Array(64)
/**
* Private Key - 32 bytes
*/
this.privateKey = new Uint8Array(32)
/**
* Public Key - 33 bytes (compressed)
*/
this.publicKey = new Uint8Array(33)
/**
* Public Key Hash160 (used to derive the parent fingerprint for derived)
*/
this.publicKeyHash = new Uint8Array(20)
/**
* Master Private Key (Base58 encoded)
*/
this.masterPrivateKey = ''
/**
* Master Public Key (Base58 encoded)
*/
this.masterPublicKey = ''
/**
* Testnet Master Private Key (Base58 encoded) - THIS IS TESTNET
*/
this._tMasterPrivateKey = ''
/**
* Testnet Master Public Key (Base58 encoded) - THIS IS TESTNET
*/
this._tmasterPublicKey = ''
/**
* Child Keys Derivation from the Parent Keys
*/
/**
* Child Private Key - 32 bytes
*/
this.childPrivateKey = new Uint8Array(32)
/**
* Child Chain Code - 32 bytes
*/
this.childChainCode = new Uint8Array(32)
/**
* Child Public Key - 33 bytes (compressed)
*/
this.childPublicKey = new Uint8Array(33)
/**
* Child Public Key Hash160 (used to derive the parent fingerprint for derived)
*/
this.childPublicKeyHash = new Uint8Array(20)
/**
* Extended Private Child Key - Base58 encoded
*/
this.xPrivateChildKey = ''
/**
* Extended Public Child Key - Base58 encoded
*/
this.xPublicChildKey = ''
/**
* Grand Child Keys Derivation from the Child Keys
*/
/**
* Grand Child Private Key - 32 bytes
*/
this.grandChildPrivateKey = new Uint8Array(32)
/**
* Grand Child Chain Code - 32 bytes
*/
this.grandChildChainCode = new Uint8Array(32)
/**
* Grand Child Public Key - 33 bytes (compressed)
*/
this.grandChildPublicKey = new Uint8Array(33)
/**
* Grand Public Key Hash160 (used to derive the parent fingerprint for derived)
*/
this.grandChildPublicKeyHash = new Uint8Array(20)
/**
* Extended Private Grand Child Key - Base58 encoded
*/
this.xPrivateGrandChildKey = ''
/**
* Extended Public Grand Child Key - Base58 encoded
*/
this.xPublicGrandChildKey = ''
/**
* Litecoin Legacy Address - Derived from the Grand Child Public Key Hash
*/
this.litecoinLegacyAddress = ''
/**
* TESTNET Litecoin Legacy Address (Derived from the Grand Child Public Key Hash) - THIS IS TESTNET
*/
this._tlitecoinLegacyAddress = ''
/**
* Wallet - Wallet Object (keys...)
*/
this.wallet = {}
}
setSeed(seed) {
this.seed = seed
}
createWallet(seed, isBIP44, indicator = null) {
// Set Seeed
this.setSeed(seed)
// Generate Seed Hash
this.generateSeedHash(this.seed, isBIP44, indicator)
// Generate Private Key
this.generatePrivateKey(this.seedHash)
// Generate Chain Code
this.generateChainCode(this.seedHash)
// Generate Public Key from Private Key
this.generatePublicKey(this.privateKey)
// Generate Mainnet Master Private Key
this.generateMainnetMasterPrivateKey()
// Generate Mainnet Master Public Key
this.generateMainnetMasterPublicKey()
// Generate Testnet Master Private Key
this.generateTestnetMasterPrivateKey()
// Generate Testnet Master Public Key
this.generateTestnetMasterPublicKey()
// Generate Child and Grand Child Keys
this.generateDerivedChildKeys()
// Return Wallet Object Specification
return this.returnWallet()
}
generateSeedHash(seed, isBIP44, indicator = null) {
let buffer;
if (isBIP44) {
buffer = utils.appendBuffer(seed.reverse(), utils.int32ToBytes(indicator))
} else {
if(indicator !== null) {
const indicatorString = utils.stringtoUTF8Array(indicator);
buffer = utils.appendBuffer(seed.reverse(), indicatorString);
}
else
{
buffer = seed.reverse();
}
}
const _reverseSeedHash = new Sha256().process(buffer).finish().result;
this.seedHash = new Sha512().process(utils.appendBuffer(seed, _reverseSeedHash)).finish().result;
}
generatePrivateKey(seedHash) {
const SECP256K1_CURVE_ORDER = new BigInteger("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141");
const privateKeyHash = seedHash.slice(0, 32);
const _privateKeyHash = [...privateKeyHash]
let privateKeyBigInt = BigInteger.fromByteArrayUnsigned(_privateKeyHash);
const privateKey = (privateKeyBigInt.mod(SECP256K1_CURVE_ORDER.subtract(BigInteger.ONE))).add(BigInteger.ONE)
this.privateKey = privateKey.toByteArrayUnsigned()
}
generateChainCode(seedHash) {
this.chainCode = new Sha256().process(seedHash.slice(32, 64)).finish().result;
}
generatePublicKey(privateKey) {
const _privateKey = [...privateKey]
const privateKeyBigInt = BigInteger.fromByteArrayUnsigned(_privateKey);
const epCurve = EllipticCurve.getSECCurveByName("secp256k1");
const curvePoints = epCurve.getG().multiply(privateKeyBigInt);
const x = curvePoints.getX().toBigInteger();
const y = curvePoints.getY().toBigInteger();
/**
* Deriving Uncompressed Public Key (65 bytes)
*
* const publicKeyBytes = EllipticCurve.integerToBytes(x, 32);
* this.publicKey = publicKeyBytes.concat(EllipticCurve.integerToBytes(y, 32));
* this.publicKey.unshift(0x04); // append point indicator
*/
// Compressed Public Key (33 bytes)
this.publicKey = EllipticCurve.integerToBytes(x, 32)
if (y.isEven()) {
this.publicKey.unshift(0x02) // append point indicator
} else {
this.publicKey.unshift(0x03) // append point indicator
}
// PublicKey Hash
const publicKeySHA256 = new Sha256().process(new Uint8Array(this.publicKey)).finish().result
const _publicKeyHash = new RIPEMD160().update(Buffer.from(publicKeySHA256)).digest('hex')
this.publicKeyHash = _publicKeyHash
}
generateMainnetMasterPrivateKey() {
// Serialization Variable
const s = []
// Append Version Byte
s.push(...(utils.int32ToBytes(this.versionBytes.mainnet.private)))
// Append Depth
s.push(this.depth)
// Append Parent Fingerprint
s.push(...(utils.int32ToBytes(this.parentFingerprint)))
// Append Child Number
s.push(...(utils.int32ToBytes(this.childIndex)))
// Append Chain Code
s.push(...this.chainCode)
// Append 1 byte '0x00' (to make the key data 33 bytes, DO THIS ONLY FOR PRIVATE KEYS )
s.push(0)
//if the private key length is less than 32 let's add leading zeros
if(this.privateKey.length<32){
for(let i=this.privateKey.length;i<32;i++){
s.push(0)
}
}
// Append Private Key
s.push(...this.privateKey)
// Generate CheckSum
const _s = new Uint8Array(s)
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
const checkSum = _checkSum.slice(0, 4)
// Append CheckSum
s.push(...checkSum) // And this brings us to the end of the serialization...
// Save to Private Key as Base58 encoded
this.masterPrivateKey = Base58.encode(s)
}
generateMainnetMasterPublicKey() {
// Serialization Variable
const s = []
// Append Version Byte
s.push(...(utils.int32ToBytes(this.versionBytes.mainnet.public)))
// Append Depth
s.push(this.depth)
// Append Parent Fingerprint
s.push(...(utils.int32ToBytes(this.parentFingerprint)))
// Append Child Number
s.push(...(utils.int32ToBytes(this.childIndex)))
// Append Chain Code
s.push(...this.chainCode)
// Append Public Key
s.push(...this.publicKey)
// Generate CheckSum
const _s = new Uint8Array(s)
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
const checkSum = _checkSum.slice(0, 4)
// Append CheckSum
s.push(...checkSum) // And this brings us to the end of the serialization...
// Save to Public Key as Base58 encoded
this.masterPublicKey = Base58.encode(s)
}
generateTestnetMasterPrivateKey() {
// To be Used ONLY in Testnet...
// Serialization Variable
const s = []
// Append Version Byte
s.push(...(utils.int32ToBytes(this.versionBytes.testnet.private)))
// Append Depth
s.push(this.depth)
// Append Parent Fingerprint
s.push(...(utils.int32ToBytes(this.parentFingerprint)))
// Append Child Number
s.push(...(utils.int32ToBytes(this.childIndex)))
// Append Chain Code
s.push(...this.chainCode)
// Append 1 byte '0x00' (to make the key data 33 bytes, DO THIS ONLY FOR PRIVATE KEYS )
s.push(0)
// Append Private Key
s.push(...this.privateKey)
// Generate CheckSum
const _s = new Uint8Array(s)
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
const checkSum = _checkSum.slice(0, 4)
// Append CheckSum
s.push(...checkSum) // And this brings us to the end of the serialization...
// Save to Private Key as Base58 encoded
this._tMasterPrivateKey = Base58.encode(s)
}
generateTestnetMasterPublicKey() {
// To be Used ONLY in Testnet...
// Serialization Variable
const s = []
// Append Version Byte
s.push(...(utils.int32ToBytes(this.versionBytes.testnet.public)))
// Append Depth
s.push(this.depth)
// Append Parent Fingerprint
s.push(...(utils.int32ToBytes(this.parentFingerprint)))
// Append Child Number
s.push(...(utils.int32ToBytes(this.childIndex)))
// Append Chain Code
s.push(...this.chainCode)
// Append Private Key
s.push(...this.publicKey)
// Generate CheckSum
const _s = new Uint8Array(s)
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
const checkSum = _checkSum.slice(0, 4)
// Append CheckSum
s.push(...checkSum) // And this brings us to the end of the serialization...
// Save to Private Key as Base58 encoded
this._tmasterPublicKey = Base58.encode(s)
}
generateDerivedChildKeys() {
// SPEC INFO: https://en.bitcoin.it/wiki/BIP_0032#Child_key_derivation_.28CKD.29_functions
// NOTE: will not be using some of derivations func as the value is known. (So I'd rather shove in the values and rewrite out the derivations later ?)
// NOTE: I "re-wrote" and "reduplicate" the code for child and grandChild keys derivations inorder to get the child and grandchild from the child
// TODO: Make this more better in the future
const path = 'm/0/0'
// let p = path.split('/');
// Get Public kEY
const derivePublicChildKey = () => {
const _privateKey = [...this.childPrivateKey]
const privateKeyBigInt = BigInteger.fromByteArrayUnsigned(_privateKey);
const epCurve = EllipticCurve.getSECCurveByName("secp256k1");
const curvePoints = epCurve.getG().multiply(privateKeyBigInt);
const x = curvePoints.getX().toBigInteger();
const y = curvePoints.getY().toBigInteger();
// Compressed Public Key (33 bytes)
this.childPublicKey = EllipticCurve.integerToBytes(x, 32)
if (y.isEven()) {
this.childPublicKey.unshift(0x02) // append point indicator
} else {
this.childPublicKey.unshift(0x03) // append point indicator
}
// PublicKey Hash
const childPublicKeySHA256 = new Sha256().process(new Uint8Array(this.childPublicKey)).finish().result
const _childPublicKeyHash = new RIPEMD160().update(Buffer.from(childPublicKeySHA256)).digest('hex')
this.childPublicKeyHash = _childPublicKeyHash
// Call deriveExtendedPublicChildKey // WIll be hardcoding the values...
deriveExtendedPublicChildKey(1, 0)
}
const derivePrivateChildKey = (cI) => {
let ib = [];
ib.push((cI >> 24) & 0xff);
ib.push((cI >> 16) & 0xff);
ib.push((cI >> 8) & 0xff);
ib.push(cI & 0xff);
const s = [...this.publicKey].concat(ib);
const _hmacSha512 = new jsSHA("SHA-512", "UINT8ARRAY", { numRounds: 1, hmacKey: { value: this.chainCode, format: "UINT8ARRAY" } });
_hmacSha512.update(new Uint8Array(s))
const IL = BigInteger.fromByteArrayUnsigned([..._hmacSha512.getHMAC('UINT8ARRAY').slice(0, 32)])
this.childChainCode = _hmacSha512.getHMAC('UINT8ARRAY').slice(32, 64) // IR according to the SPEC
// SECP256k1 init
const epCurve = EllipticCurve.getSECCurveByName("secp256k1");
const ki = IL.add(BigInteger.fromByteArrayUnsigned(this.privateKey)).mod(epCurve.getN()); // parse256(IL) + kpar (mod n) ==> ki
this.childPrivateKey = ki.toByteArrayUnsigned()
// Call deriveExtendedPrivateChildKey
deriveExtendedPrivateChildKey(1, 0)
}
const deriveExtendedPrivateChildKey = (i, childIndex) => {
// Serialization Variable
const s = []
// Append Version Byte
s.push(...(utils.int32ToBytes(this.versionBytes.mainnet.private)))
// Append Depth (using the index as depth)
i = parseInt(i)
s.push(i)
// Append Parent Fingerprint
s.push(...(this.publicKeyHash.slice(0, 4)))
// Append Child Index
s.push(childIndex >>> 24);
s.push((childIndex >>> 16) & 0xff);
s.push((childIndex >>> 8) & 0xff);
s.push(childIndex & 0xff);
// Append Chain Code
s.push(...this.childChainCode)
// Append 1 byte '0x00' (to make the key data 33 bytes, DO THIS ONLY FOR PRIVATE KEYS )
s.push(0)
// Append Private Key
s.push(...this.childPrivateKey)
// Generate CheckSum
const _s = new Uint8Array(s)
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
const checkSum = _checkSum.slice(0, 4)
// Append CheckSum
s.push(...checkSum) // And this brings us to the end of the serialization...
// Save to Private Key as Base58 encoded
this.xPrivateChildKey = Base58.encode(s)
}
const deriveExtendedPublicChildKey = (i, childIndex) => {
// Serialization Variable
const s = []
// Append Version Byte
s.push(...(utils.int32ToBytes(this.versionBytes.mainnet.public)))
// Append Depth
i = parseInt(i)
s.push(i)
// Append Parent Fingerprint
s.push(...(this.publicKeyHash.slice(0, 4)))
// Append Child Index
s.push(childIndex >>> 24);
s.push((childIndex >>> 16) & 0xff);
s.push((childIndex >>> 8) & 0xff);
s.push(childIndex & 0xff);
// Append Chain Code
s.push(...this.childChainCode)
// Append Public Key
s.push(...this.childPublicKey)
// Generate CheckSum
const _s = new Uint8Array(s)
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
const checkSum = _checkSum.slice(0, 4)
// Append CheckSum
s.push(...checkSum) // And this brings us to the end of the serialization...
// Save to Public Key as Base58 encoded
this.xPublicChildKey = Base58.encode(s)
}
/**
* GRAND CHILD KEYS
*
* NOTE: I know this is not the best way to generate this (even though it works the way it ought)
* Things to rewrite will be and not limited to deriving this through a for loop, removing hard code values, etc...
*/
const derivePublicGrandChildKey = () => {
const _privateKey = [...this.grandChildPrivateKey]
const privateKeyBigInt = BigInteger.fromByteArrayUnsigned(_privateKey);
const epCurve = EllipticCurve.getSECCurveByName("secp256k1");
const curvePoints = epCurve.getG().multiply(privateKeyBigInt);
const x = curvePoints.getX().toBigInteger();
const y = curvePoints.getY().toBigInteger();
// Compressed Public Key (33 bytes)
this.grandChildPublicKey = EllipticCurve.integerToBytes(x, 32)
if (y.isEven()) {
this.grandChildPublicKey.unshift(0x02) // append point indicator
} else {
this.grandChildPublicKey.unshift(0x03) // append point indicator
}
// PublicKey Hash
const grandChildPublicKeySHA256 = new Sha256().process(new Uint8Array(this.grandChildPublicKey)).finish().result
const _grandChildPublicKeyHash = new RIPEMD160().update(Buffer.from(grandChildPublicKeySHA256)).digest('hex')
this.grandChildPublicKeyHash = _grandChildPublicKeyHash
// Call deriveExtendedPublicChildKey // WIll be hardcoding the values...
deriveExtendedPublicGrandChildKey(2, 0)
/**
* Derive Litecoin Legacy Address
*/
// Append Address Prefix
const k = [this.versionBytes.mainnet.prefix].concat(...this.grandChildPublicKeyHash)
// Derive Checksum
const _addressCheckSum = new Sha256().process(new Sha256().process(new Uint8Array(k)).finish().result).finish().result
const addressCheckSum = _addressCheckSum.slice(0, 4)
// Append CheckSum
const _litecoinLegacyAddress = k.concat(...addressCheckSum)
// Convert to Base58
this.litecoinLegacyAddress = Base58.encode(_litecoinLegacyAddress)
/**
* Derive TESTNET Litecoin Legacy Address
*/
// Append Version Byte
const tK = [this.versionBytes.testnet.prefix].concat(...this.grandChildPublicKeyHash)
// Derive Checksum
const _tAddressCheckSum = new Sha256().process(new Sha256().process(new Uint8Array(tK)).finish().result).finish().result
const tAddressCheckSum = _tAddressCheckSum.slice(0, 4)
// Append CheckSum
const _tlitecoinLegacyAddress = tK.concat(...tAddressCheckSum)
// Convert to Base58
this._tlitecoinLegacyAddress = Base58.encode(_tlitecoinLegacyAddress)
}
const derivePrivateGrandChildKey = (cI, i) => {
let ib = [];
ib.push((cI >> 24) & 0xff);
ib.push((cI >> 16) & 0xff);
ib.push((cI >> 8) & 0xff);
ib.push(cI & 0xff);
const s = [...this.childPublicKey].concat(ib);
const _hmacSha512 = new jsSHA("SHA-512", "UINT8ARRAY", { numRounds: 1, hmacKey: { value: this.childChainCode, format: "UINT8ARRAY" } });
_hmacSha512.update(new Uint8Array(s))
const IL = BigInteger.fromByteArrayUnsigned([..._hmacSha512.getHMAC('UINT8ARRAY').slice(0, 32)])
this.grandChildChainCode = _hmacSha512.getHMAC('UINT8ARRAY').slice(32, 64) // IR according to the SPEC
// SECP256k1 init
const epCurve = EllipticCurve.getSECCurveByName("secp256k1");
const ki = IL.add(BigInteger.fromByteArrayUnsigned(this.childPrivateKey)).mod(epCurve.getN()); // parse256(IL) + kpar (mod n) ==> ki
this.grandChildPrivateKey = ki.toByteArrayUnsigned()
// Call deriveExtendedPrivateChildKey
deriveExtendedPrivateGrandChildKey(2, 0)
}
const deriveExtendedPrivateGrandChildKey = (i, childIndex) => {
// Serialization Variable
const s = []
// Append Version Byte
s.push(...(utils.int32ToBytes(this.versionBytes.mainnet.private)))
// Append Depth (using the index as depth)
i = parseInt(i)
s.push(i)
// Append Parent Fingerprint
s.push(...(this.childPublicKeyHash.slice(0, 4)))
// Append Child Index
s.push(childIndex >>> 24);
s.push((childIndex >>> 16) & 0xff);
s.push((childIndex >>> 8) & 0xff);
s.push(childIndex & 0xff);
// Append Chain Code
s.push(...this.grandChildChainCode)
// Append 1 byte '0x00' (to make the key data 33 bytes, DO THIS ONLY FOR PRIVATE KEYS )
s.push(0)
// Append Private Key
s.push(...this.grandChildPrivateKey)
// Generate CheckSum
const _s = new Uint8Array(s)
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
const checkSum = _checkSum.slice(0, 4)
// Append CheckSum
s.push(...checkSum) // And this brings us to the end of the serialization...
// Save to Private Key as Base58 encoded
this.xPrivateGrandChildKey = Base58.encode(s)
}
const deriveExtendedPublicGrandChildKey = (i, childIndex) => {
// Serialization Variable
const s = []
// Append Version Byte
s.push(...(utils.int32ToBytes(this.versionBytes.mainnet.public)))
// Append Depth
i = parseInt(i)
s.push(i)
// Append Parent Fingerprint
s.push(...(this.childPublicKeyHash.slice(0, 4)))
// Append Child Index
s.push(childIndex >>> 24);
s.push((childIndex >>> 16) & 0xff);
s.push((childIndex >>> 8) & 0xff);
s.push(childIndex & 0xff);
// Append Chain Code
s.push(...this.grandChildChainCode)
// Append Public Key
s.push(...this.grandChildPublicKey)
// Generate CheckSum
const _s = new Uint8Array(s)
const _checkSum = new Sha256().process(new Sha256().process(_s).finish().result).finish().result
const checkSum = _checkSum.slice(0, 4)
// Append CheckSum
s.push(...checkSum) // And this brings us to the end of the serialization...
// Save to Public Key as Base58 encoded
this.xPublicGrandChildKey = Base58.encode(s)
}
// Hard Code value..
let childIndex = 0
// Call derivePrivateChildKey //Hard code value
derivePrivateChildKey(childIndex)
// Call derivePublicChildKey
derivePublicChildKey()
// Call derivePrivateGrandChildKey // Hard Code value...
derivePrivateGrandChildKey(0, 2)
// Call derivePublicGrandChildKey
derivePublicGrandChildKey()
}
returnWallet() {
// Will be limiting the exported Wallet Object to just the Master keys and Legacy Addresses
const wallet = {
derivedMasterPrivateKey: this.masterPrivateKey,
derivedMasterPublicKey: this.masterPublicKey,
_tDerivedMasterPrivateKey: this._tMasterPrivateKey,
_tDerivedmasterPublicKey: this._tmasterPublicKey,
// derivedPrivateChildKey: this.xPrivateChildKey,
// derivedPublicChildKey: this.xPublicChildKey,
// derivedPrivateGrandChildKey: this.xPrivateGrandChildKey,
// derivedPublicGrandChildKey: this.xPublicGrandChildKey,
address: this.litecoinLegacyAddress,
_taddress: this._tlitecoinLegacyAddress
}
this.wallet = wallet
return wallet
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,294 @@
"use strict";
// This needs a total makeover.
// Qortal TX types
const TX_TYPES = {
1: "Genesis",
2: "Payment",
3: "Name registration",
4: "Name update",
5: "Sell name",
6: "Cancel sell name",
7: "Buy name",
8: "Create poll",
9: "Vote in poll",
10: "Arbitrary",
11: "Issue asset",
12: "Transfer asset",
13: "Create asset order",
14: "Cancel asset order",
15: "Multi-payment transaction",
16: "Deploy AT",
17: "Message",
18: "Chat",
19: "Publicize",
20: "Airdrop",
21: 'AT',
22: 'Create group',
23: 'Update group',
24: 'Add group admin',
25: 'Remove group admin',
26: 'Group ban',
27: 'Cancel group ban',
28: 'Group kick',
29: 'Group invite',
30: 'Cancel group invite',
31: 'Join group',
32: 'Leave group',
33: 'Group approval',
34: 'Set group',
35: 'Update asset',
36: 'Account flags',
37: 'Enable forging',
38: 'Reward share',
39: 'Account level',
}
// Qortal errors
// OK(1),
// INVALID_ADDRESS(2),
// NEGATIVE_AMOUNT(3),
// NEGATIVE_FEE(4),
// NO_BALANCE(5),
// INVALID_REFERENCE(6),
// INVALID_NAME_LENGTH(7),
// INVALID_VALUE_LENGTH(8),
// NAME_ALREADY_REGISTERED(9),
// NAME_DOES_NOT_EXIST(10),
// INVALID_NAME_OWNER(11),
// NAME_ALREADY_FOR_SALE(12),
// NAME_NOT_FOR_SALE(13),
// BUYER_ALREADY_OWNER(14),
// INVALID_AMOUNT(15),
// INVALID_SELLER(16),
// NAME_NOT_LOWER_CASE(17),
// INVALID_DESCRIPTION_LENGTH(18),
// INVALID_OPTIONS_COUNT(19),
// INVALID_OPTION_LENGTH(20),
// DUPLICATE_OPTION(21),
// POLL_ALREADY_EXISTS(22),
// POLL_DOES_NOT_EXIST(24),
// POLL_OPTION_DOES_NOT_EXIST(25),
// ALREADY_VOTED_FOR_THAT_OPTION(26),
// INVALID_DATA_LENGTH(27),
// INVALID_QUANTITY(28),
// ASSET_DOES_NOT_EXIST(29),
// INVALID_RETURN(30),
// HAVE_EQUALS_WANT(31),
// ORDER_DOES_NOT_EXIST(32),
// INVALID_ORDER_CREATOR(33),
// INVALID_PAYMENTS_COUNT(34),
// NEGATIVE_PRICE(35),
// INVALID_CREATION_BYTES(36),
// INVALID_TAGS_LENGTH(37),
// INVALID_AT_TYPE_LENGTH(38),
// INVALID_AT_TRANSACTION(39),
// INSUFFICIENT_FEE(40),
// ASSET_DOES_NOT_MATCH_AT(41),
// ASSET_ALREADY_EXISTS(43),
// MISSING_CREATOR(44),
// TIMESTAMP_TOO_OLD(45),
// TIMESTAMP_TOO_NEW(46),
// TOO_MANY_UNCONFIRMED(47),
// GROUP_ALREADY_EXISTS(48),
// GROUP_DOES_NOT_EXIST(49),
// INVALID_GROUP_OWNER(50),
// ALREADY_GROUP_MEMBER(51),
// GROUP_OWNER_CANNOT_LEAVE(52),
// NOT_GROUP_MEMBER(53),
// ALREADY_GROUP_ADMIN(54),
// NOT_GROUP_ADMIN(55),
// INVALID_LIFETIME(56),
// INVITE_UNKNOWN(57),
// BAN_EXISTS(58),
// BAN_UNKNOWN(59),
// BANNED_FROM_GROUP(60),
// JOIN_REQUEST_EXISTS(61),
// INVALID_GROUP_APPROVAL_THRESHOLD(62),
// GROUP_ID_MISMATCH(63),
// INVALID_GROUP_ID(64),
// TRANSACTION_UNKNOWN(65),
// TRANSACTION_ALREADY_CONFIRMED(66),
// INVALID_TX_GROUP_ID(67),
// TX_GROUP_ID_MISMATCH(68),
// MULTIPLE_NAMES_FORBIDDEN(69),
// INVALID_ASSET_OWNER(70),
// AT_IS_FINISHED(71),
// NO_FLAG_PERMISSION(72),
// NOT_MINTING_ACCOUNT(73),
// INVALID_REWARD_SHARE_PERCENT(77),
// PUBLIC_KEY_UNKNOWN(78),
// INVALID_PUBLIC_KEY(79),
// AT_UNKNOWN(80),
// AT_ALREADY_EXISTS(81),
// GROUP_APPROVAL_NOT_REQUIRED(82),
// GROUP_APPROVAL_DECIDED(83),
// MAXIMUM_REWARD_SHARES(84),
// TRANSACTION_ALREADY_EXISTS(85),
// NO_BLOCKCHAIN_LOCK(86),
// ORDER_ALREADY_CLOSED(87),
// CLOCK_NOT_SYNCED(88),
// ASSET_NOT_SPENDABLE(89),
// ACCOUNT_CANNOT_REWARD_SHARE(90),
// NOT_YET_RELEASED(1000);
const ERROR_CODES = {
1: "Valid OK",
2: "Invalid address",
3: "Negative amount",
4: "Nagative fee",
5: "No balance",
6: "Invalid reference",
7: "Invalid time length",
8: "Invalid value length",
9: "Name already registered",
10: "Name does not exist",
11: "Invalid name owner",
12: "Name already for sale",
13: "Name not for sale",
14: "Name buyer already owner",
15: "Invalid amount",
16: "Invalid seller",
17: "Name not lowercase",
18: "Invalid description length",
19: "Invalid options length",
20: "Invalid option length",
21: "Duplicate option",
22: "Poll already created",
23: "Poll already has votes",
24: "Poll does not exist",
25: "Option does not exist",
26: "Already voted for that option",
27: "Invalid data length",
28: "Invalid quantity",
29: "Asset does not exist",
30: "Invalid return",
31: "Have equals want",
32: "Order does not exist",
33: "Invalid order creator",
34: "Invalid payments length",
35: "Negative price",
36: "Invalid creation bytes",
37: "Invalid tags length",
38: "Invalid type length",
39: 'Invalid AT transaction',
40: "Insufficient fee",
41: "Asset does not match AT",
43: 'Asset already exists',
44: 'Missing creator',
45: 'Timestamp too old',
46: 'Timestamp too new',
47: 'Too many unconfirmed',
48: 'Group already exists',
49: 'Group does not exist',
50: 'Invalid group owner',
51: 'Already group memeber',
52: 'Group owner can not leave',
53: 'Not group member',
54: 'Already group admin',
55: 'Not group admin',
56: 'Invalid lifetime',
57: 'Invite unknown',
58: 'Ban exists', // total crap mistakes by the nigerian scammer
59: 'Ban unknown', // its fucking Ban not Ben
60: 'Banned from group',
61: 'Join request',
62: 'Invalid group approval threshold',
63: 'Group ID mismatch',
64: 'Invalid group ID',
65: 'Transaction unknown',
66: 'Transaction already confirmed',
67: 'Invalid TX group',
68: 'TX group ID mismatch',
69: 'Multiple names forbidden',
70: 'Invalid asset owner',
71: 'AT is finished',
72: 'No flag permission',
73: 'Not minting accout',
77: 'Invalid rewardshare percent',
78: 'Public key unknown',
79: 'Invalid public key',
80: 'AT unknown',
81: 'AT already exists',
82: 'Group approval not required',
83: 'Group approval decided',
84: 'Maximum reward shares',
85: 'Transaction already exists',
86: 'No blockchain lock',
87: 'Order already closed',
88: 'Clock not synced',
89: 'Asset not spendable',
90: 'Account can not reward share',
1000: "Not yet released."
}
const QORT_DECIMALS = 1e8
const PROXY_URL = "/proxy/" // Proxy for api calls
const ADDRESS_VERSION = 58; // Q for Qora
// const ADDRESS_VERSION = 46; // K for Karma
// Used as a salt for all qora addresses. Salts used for storing your private keys in local storage will be randomly generated
const STATIC_SALT = new Uint8Array([54, 190, 201, 206, 65, 29, 123, 129, 147, 231, 180, 166, 171, 45, 95, 165, 78, 200, 208, 194, 44, 207, 221, 146, 45, 238, 68, 68, 69, 102, 62, 6])
const BCRYPT_ROUNDS = 10 // Remember that the total work spent on key derivation is BCRYPT_ROUNDS * KDF_THREADS
const BCRYPT_VERSION = "2a"
const STATIC_BCRYPT_SALT = `$${BCRYPT_VERSION}$${BCRYPT_ROUNDS}$IxVE941tXVUD4cW0TNVm.O`
// const PBKDF2_ROUNDS = Math.pow(2,17) // Deprecated
const KDF_THREADS = 16 // 16 Threads seems like a good number :) . No you dumbass nigerian. Its not ! -_-
export { TX_TYPES, ERROR_CODES, QORT_DECIMALS, PROXY_URL, STATIC_SALT, ADDRESS_VERSION, KDF_THREADS, STATIC_BCRYPT_SALT }
//const TX_TYPES = {
// GENESIS_TRANSACTION: 1,
// PAYMENT_TRANSACTION: 2,
//
// REGISTER_NAME_TRANSACTION: 3,
// UPDATE_NAME_TRANSACTION: 4,
// SELL_NAME_TRANSACTION: 5,
// CANCEL_SELL_NAME_TRANSACTION: 6,
// BUY_NAME_TRANSACTION: 7,
//
// CREATE_POLL_TRANSACTION: 8,
// VOTE_ON_POLL_TRANSACTION: 9,
//
// ARBITRARY_TRANSACTION: 10,
//
// ISSUE_ASSET_TRANSACTION: 11,
// TRANSFER_ASSET_TRANSACTION: 12,
// CREATE_ORDER_TRANSACTION: 13,
// CANCEL_ORDER_TRANSACTION: 14,
// MULTI_PAYMENT_TRANSACTION: 15,
//
// DEPLOY_AT_TRANSACTION: 16,
//
// MESSAGE_TRANSACTION: 17
//};

View File

@@ -0,0 +1,32 @@
import { transactionTypes as transactions } from './transactions/transactions.js'
import Base58 from './deps/Base58.js'
import { request } from './fetch-request'
import signChat from './transactions/chat/signChat.js'
export const createTransaction = (type, keyPair, params) => {
const tx = new transactions[type]()
tx.keyPair = keyPair
Object.keys(params).forEach(param => {
tx[param] = params[param]
})
return tx
}
// Compute Chat Nonce
export const computeChatNonce = bytes => request('/chat/compute', {
method: 'POST',
body: Base58.encode(bytes)
})
// Sign Chat Transactions
export const signChatTransaction = (chatBytes, nonce, keyPair) => {
return signChat(chatBytes, nonce, keyPair)
}
// Process Transactions
export const processTransaction = bytes => request('/transactions/process', {
method: 'POST',
body: Base58.encode(bytes)
})

View File

@@ -0,0 +1,30 @@
import { kdf } from './kdf.js'
import PhraseWallet from './PhraseWallet.js'
import Base58 from './deps/Base58.js'
import { decryptStoredWallet } from './decryptStoredWallet.js'
export const createWallet = async (sourceType, source, statusUpdateFn) => {
let version, seed
switch (sourceType) {
case 'phrase':
version = 2
seed = await kdf(source.seedPhrase, void 0, statusUpdateFn)
break
case 'seed':
version = 1
seed = Base58.decode(source.seed)
break
case 'storedWallet':
case 'backedUpSeed':
version = source.wallet.version
seed = await decryptStoredWallet(source.password, source.wallet, statusUpdateFn)
break
default:
throw 'sourceType ' + sourceType + ' not recognized'
}
const wallet = new PhraseWallet(seed, version)
return wallet
}

View File

@@ -0,0 +1,23 @@
import Base58 from './deps/Base58.js'
import { kdf } from './kdf.js'
import { HmacSha512, AES_CBC } from 'asmcrypto.js'
export const decryptStoredWallet = async (password, wallet, statusFn = () => { }) => {
statusFn('Decoding saved data')
const encryptedSeedBytes = Base58.decode(wallet.encryptedSeed)
const iv = Base58.decode(wallet.iv)
const salt = Base58.decode(wallet.salt)
statusFn('Generating decryption key')
const key = await kdf(password, salt, statusFn)
const encryptionKey = key.slice(0, 32)
const macKey = key.slice(32, 63)
statusFn('Checking key')
const mac = new HmacSha512(macKey).process(encryptedSeedBytes).finish().result
if (Base58.encode(mac) !== wallet.mac) {
throw new Error('Incorrect password')
}
statusFn('Decrypting')
const decryptedBytes = AES_CBC.decrypt(encryptedSeedBytes, encryptionKey, false, iv)
return decryptedBytes
}

View File

@@ -0,0 +1,108 @@
// Generated by CoffeeScript 1.8.0
// == Changed for ES6 modules == //
//(function() {
//var ALPHABET, ALPHABET_MAP, Base58, i;
//const Base58 = (typeof module !== "undefined" && module !== null ? module.exports : void 0) || (window.Base58 = {});
const Base58 = {};
const ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
const ALPHABET_MAP = {};
let i = 0;
while (i < ALPHABET.length) {
ALPHABET_MAP[ALPHABET.charAt(i)] = i;
i++;
}
Base58.encode = function(buffer) {
buffer = new Uint8Array(buffer);
var carry, digits, j;
if (buffer.length === 0) {
return "";
}
i = void 0;
j = void 0;
digits = [0];
i = 0;
while (i < buffer.length) {
j = 0;
while (j < digits.length) {
digits[j] <<= 8;
j++;
}
digits[0] += buffer[i];
carry = 0;
j = 0;
while (j < digits.length) {
digits[j] += carry;
carry = (digits[j] / 58) | 0;
digits[j] %= 58;
++j;
}
while (carry) {
digits.push(carry % 58);
carry = (carry / 58) | 0;
}
i++;
}
i = 0;
while (buffer[i] === 0 && i < buffer.length - 1) {
digits.push(0);
i++;
}
return digits.reverse().map(function(digit) {
return ALPHABET[digit];
}).join("");
};
Base58.decode = function(string) {
var bytes, c, carry, j;
if (string.length === 0) {
return new (typeof Uint8Array !== "undefined" && Uint8Array !== null ? Uint8Array : Buffer)(0);
}
i = void 0;
j = void 0;
bytes = [0];
i = 0;
while (i < string.length) {
c = string[i];
if (!(c in ALPHABET_MAP)) {
throw "Base58.decode received unacceptable input. Character '" + c + "' is not in the Base58 alphabet.";
}
j = 0;
while (j < bytes.length) {
bytes[j] *= 58;
j++;
}
bytes[0] += ALPHABET_MAP[c];
carry = 0;
j = 0;
while (j < bytes.length) {
bytes[j] += carry;
carry = bytes[j] >> 8;
bytes[j] &= 0xff;
++j;
}
while (carry) {
bytes.push(carry & 0xff);
carry >>= 8;
}
i++;
}
i = 0;
while (string[i] === "1" && i < string.length - 1) {
bytes.push(0);
i++;
}
return new (typeof Uint8Array !== "undefined" && Uint8Array !== null ? Uint8Array : Buffer)(bytes.reverse());
};
// == Changed for ES6 modules == //
//}).call(this);
export default Base58;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,180 @@
// "Generated from Java with JSweet 1.0.0 - http://www.jsweet.org";
// BAD IMPLEMENTATION. BROKEN, BUT MUST KEEP CAUSE OF NETWORK
//const RIPEMD160 = (function () {
// == Convert to ES6 module for export == //
const RIPEMD160 = (function () {
function RIPEMD160() {
this.MDbuf = [];
this.MDbuf[0] = 1732584193;
this.MDbuf[1] = -271733879;
this.MDbuf[2] = -1732584194;
this.MDbuf[3] = 271733878;
this.MDbuf[4] = -1009589776;
this.working = new Int32Array(16);
this.working_ptr = 0;
this.msglen = 0;
}
RIPEMD160.prototype.reset = function () {
this.MDbuf = [];
this.MDbuf[0] = 1732584193;
this.MDbuf[1] = -271733879;
this.MDbuf[2] = -1732584194;
this.MDbuf[3] = 271733878;
this.MDbuf[4] = -1009589776;
this.working = new Int32Array(16);
this.working_ptr = 0;
this.msglen = 0;
};
RIPEMD160.prototype.compress = function (X) {
var index = 0;
var a;
var b;
var c;
var d;
var e;
var A;
var B;
var C;
var D;
var E;
var temp;
var s;
A = a = this.MDbuf[0];
B = b = this.MDbuf[1];
C = c = this.MDbuf[2];
D = d = this.MDbuf[3];
E = e = this.MDbuf[4];
for (; index < 16; index++) {
temp = a + (b ^ c ^ d) + X[RIPEMD160.IndexArray[0][index]];
a = e;
e = d;
d = (c << 10) | (c >>> 22);
c = b;
s = RIPEMD160.ArgArray[0][index];
b = ((temp << s) | (temp >>> (32 - s))) + a;
temp = A + (B ^ (C | ~D)) + X[RIPEMD160.IndexArray[1][index]] + 1352829926;
A = E;
E = D;
D = (C << 10) | (C >>> 22);
C = B;
s = RIPEMD160.ArgArray[1][index];
B = ((temp << s) | (temp >>> (32 - s))) + A;
}
for (; index < 32; index++) {
temp = a + ((b & c) | (~b & d)) + X[RIPEMD160.IndexArray[0][index]] + 1518500249;
a = e;
e = d;
d = (c << 10) | (c >>> 22);
c = b;
s = RIPEMD160.ArgArray[0][index];
b = ((temp << s) | (temp >>> (32 - s))) + a;
temp = A + ((B & D) | (C & ~D)) + X[RIPEMD160.IndexArray[1][index]] + 1548603684;
A = E;
E = D;
D = (C << 10) | (C >>> 22);
C = B;
s = RIPEMD160.ArgArray[1][index];
B = ((temp << s) | (temp >>> (32 - s))) + A;
}
for (; index < 48; index++) {
temp = a + ((b | ~c) ^ d) + X[RIPEMD160.IndexArray[0][index]] + 1859775393;
a = e;
e = d;
d = (c << 10) | (c >>> 22);
c = b;
s = RIPEMD160.ArgArray[0][index];
b = ((temp << s) | (temp >>> (32 - s))) + a;
temp = A + ((B | ~C) ^ D) + X[RIPEMD160.IndexArray[1][index]] + 1836072691;
A = E;
E = D;
D = (C << 10) | (C >>> 22);
C = B;
s = RIPEMD160.ArgArray[1][index];
B = ((temp << s) | (temp >>> (32 - s))) + A;
}
for (; index < 64; index++) {
temp = a + ((b & d) | (c & ~d)) + X[RIPEMD160.IndexArray[0][index]] + -1894007588;
a = e;
e = d;
d = (c << 10) | (c >>> 22);
c = b;
s = RIPEMD160.ArgArray[0][index];
b = ((temp << s) | (temp >>> (32 - s))) + a;
temp = A + ((B & C) | (~B & D)) + X[RIPEMD160.IndexArray[1][index]] + 2053994217;
A = E;
E = D;
D = (C << 10) | (C >>> 22);
C = B;
s = RIPEMD160.ArgArray[1][index];
B = ((temp << s) | (temp >>> (32 - s))) + A;
}
for (; index < 80; index++) {
temp = a + (b ^ (c | ~d)) + X[RIPEMD160.IndexArray[0][index]] + -1454113458;
a = e;
e = d;
d = (c << 10) | (c >>> 22);
c = b;
s = RIPEMD160.ArgArray[0][index];
b = ((temp << s) | (temp >>> (32 - s))) + a;
temp = A + (B ^ C ^ D) + X[RIPEMD160.IndexArray[1][index]];
A = E;
E = D;
D = (C << 10) | (C >>> 22);
C = B;
s = RIPEMD160.ArgArray[1][index];
B = ((temp << s) | (temp >>> (32 - s))) + A;
}
D += c + this.MDbuf[1];
this.MDbuf[1] = this.MDbuf[2] + d + E;
this.MDbuf[2] = this.MDbuf[3] + e + A;
this.MDbuf[3] = this.MDbuf[4] + a + B;
this.MDbuf[4] = this.MDbuf[0] + b + C;
this.MDbuf[0] = D;
};
RIPEMD160.prototype.MDfinish = function (array, lswlen, mswlen) {
var X = array;
X[(lswlen >> 2) & 15] ^= 1 << (((lswlen & 3) << 3) + 7);
if (((lswlen & 63) > 55)) {
this.compress(X);
for (var i = 0; i < 14; i++) {
X[i] = 0;
}
}
X[14] = lswlen << 3;
X[15] = (lswlen >> 29) | (mswlen << 3);
this.compress(X);
};
RIPEMD160.prototype.update = function (input) {
for (var i = 0; i < input.length; i++) {
this.working[this.working_ptr >> 2] ^= input[i] << ((this.working_ptr & 3) << 3);
this.working_ptr++;
if ((this.working_ptr == 64)) {
this.compress(this.working);
for (var j = 0; j < 16; j++) {
this.working[j] = 0;
}
this.working_ptr = 0;
}
}
this.msglen += input.length;
};
RIPEMD160.prototype.digestBin = function () {
this.MDfinish(this.working, this.msglen, 0);
//var res = new Int8Array();
var res = [];
for (var i = 0; i < 20; i++) {
res[i] = ((this.MDbuf[i >> 2] >>> ((i & 3) << 3)) & 255);
}
return new Uint8Array(res);
};
RIPEMD160.prototype.digest = function (input) {
this.update(new Int8Array(input));
return this.digestBin();
};
RIPEMD160.ArgArray = [[11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12, 9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6], [8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8, 8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11]];
RIPEMD160.IndexArray = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2, 4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13], [5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14, 12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11]];
return RIPEMD160;
})();
export default RIPEMD160

View File

@@ -0,0 +1,3 @@
export { default as Base58 } from './Base58.js'
export { default as utils } from './utils.js'

View File

@@ -0,0 +1,264 @@
/*
* ed2curve: convert Ed25519 signing key pair into Curve25519
* key pair suitable for Diffie-Hellman key exchange.
*
* Written by Dmitry Chestnykh in 2014. Public domain.
*/
/* jshint newcap: false */
/*
Change to es6 import/export
*/
import nacl from './nacl-fast.js'
// (function(root, f) {
// 'use strict';
// if (typeof module !== 'undefined' && module.exports) module.exports = f(require('tweetnacl'));
// else root.ed2curve = f(root.nacl);
// }(this, function(nacl) {
// 'use strict';
// if (!nacl) throw new Error('tweetnacl not loaded');
// -- Operations copied from TweetNaCl.js. --
var gf = function(init) {
var i, r = new Float64Array(16);
if (init) for (i = 0; i < init.length; i++) r[i] = init[i];
return r;
};
var gf0 = gf(),
gf1 = gf([1]),
D = gf([0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203]),
I = gf([0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83]);
function car25519(o) {
var c;
var i;
for (i = 0; i < 16; i++) {
o[i] += 65536;
c = Math.floor(o[i] / 65536);
o[(i+1)*(i<15?1:0)] += c - 1 + 37 * (c-1) * (i===15?1:0);
o[i] -= (c * 65536);
}
}
function sel25519(p, q, b) {
var t, c = ~(b-1);
for (var i = 0; i < 16; i++) {
t = c & (p[i] ^ q[i]);
p[i] ^= t;
q[i] ^= t;
}
}
function unpack25519(o, n) {
var i;
for (i = 0; i < 16; i++) o[i] = n[2*i] + (n[2*i+1] << 8);
o[15] &= 0x7fff;
}
// addition
function A(o, a, b) {
var i;
for (i = 0; i < 16; i++) o[i] = (a[i] + b[i])|0;
}
// subtraction
function Z(o, a, b) {
var i;
for (i = 0; i < 16; i++) o[i] = (a[i] - b[i])|0;
}
// multiplication
function M(o, a, b) {
var i, j, t = new Float64Array(31);
for (i = 0; i < 31; i++) t[i] = 0;
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j++) {
t[i+j] += a[i] * b[j];
}
}
for (i = 0; i < 15; i++) {
t[i] += 38 * t[i+16];
}
for (i = 0; i < 16; i++) o[i] = t[i];
car25519(o);
car25519(o);
}
// squaring
function S(o, a) {
M(o, a, a);
}
// inversion
function inv25519(o, i) {
var c = gf();
var a;
for (a = 0; a < 16; a++) c[a] = i[a];
for (a = 253; a >= 0; a--) {
S(c, c);
if(a !== 2 && a !== 4) M(c, c, i);
}
for (a = 0; a < 16; a++) o[a] = c[a];
}
function pack25519(o, n) {
var i, j, b;
var m = gf(), t = gf();
for (i = 0; i < 16; i++) t[i] = n[i];
car25519(t);
car25519(t);
car25519(t);
for (j = 0; j < 2; j++) {
m[0] = t[0] - 0xffed;
for (i = 1; i < 15; i++) {
m[i] = t[i] - 0xffff - ((m[i-1]>>16) & 1);
m[i-1] &= 0xffff;
}
m[15] = t[15] - 0x7fff - ((m[14]>>16) & 1);
b = (m[15]>>16) & 1;
m[14] &= 0xffff;
sel25519(t, m, 1-b);
}
for (i = 0; i < 16; i++) {
o[2*i] = t[i] & 0xff;
o[2*i+1] = t[i] >> 8;
}
}
function par25519(a) {
var d = new Uint8Array(32);
pack25519(d, a);
return d[0] & 1;
}
function vn(x, xi, y, yi, n) {
var i, d = 0;
for (i = 0; i < n; i++) d |= x[xi + i] ^ y[yi + i];
return (1 & ((d - 1) >>> 8)) - 1;
}
function crypto_verify_32(x, xi, y, yi) {
return vn(x, xi, y, yi, 32);
}
function neq25519(a, b) {
var c = new Uint8Array(32), d = new Uint8Array(32);
pack25519(c, a);
pack25519(d, b);
return crypto_verify_32(c, 0, d, 0);
}
function pow2523(o, i) {
var c = gf();
var a;
for (a = 0; a < 16; a++) c[a] = i[a];
for (a = 250; a >= 0; a--) {
S(c, c);
if (a !== 1) M(c, c, i);
}
for (a = 0; a < 16; a++) o[a] = c[a];
}
function set25519(r, a) {
var i;
for (i = 0; i < 16; i++) r[i] = a[i] | 0;
}
function unpackneg(r, p) {
var t = gf(), chk = gf(), num = gf(),
den = gf(), den2 = gf(), den4 = gf(),
den6 = gf();
set25519(r[2], gf1);
unpack25519(r[1], p);
S(num, r[1]);
M(den, num, D);
Z(num, num, r[2]);
A(den, r[2], den);
S(den2, den);
S(den4, den2);
M(den6, den4, den2);
M(t, den6, num);
M(t, t, den);
pow2523(t, t);
M(t, t, num);
M(t, t, den);
M(t, t, den);
M(r[0], t, den);
S(chk, r[0]);
M(chk, chk, den);
if (neq25519(chk, num)) M(r[0], r[0], I);
S(chk, r[0]);
M(chk, chk, den);
if (neq25519(chk, num)) return -1;
if (par25519(r[0]) === (p[31] >> 7)) Z(r[0], gf0, r[0]);
M(r[3], r[0], r[1]);
return 0;
}
// ----
// Converts Ed25519 public key to Curve25519 public key.
// montgomeryX = (edwardsY + 1)*inverse(1 - edwardsY) mod p
function convertPublicKey(pk) {
var z = new Uint8Array(32),
q = [gf(), gf(), gf(), gf()],
a = gf(), b = gf();
if (unpackneg(q, pk)) return null; // reject invalid key
var y = q[1];
A(a, gf1, y);
Z(b, gf1, y);
inv25519(b, b);
M(a, a, b);
pack25519(z, a);
return z;
}
// Converts Ed25519 secret key to Curve25519 secret key.
function convertSecretKey(sk) {
var d = new Uint8Array(64), o = new Uint8Array(32), i;
nacl.lowlevel.crypto_hash(d, sk, 32);
d[0] &= 248;
d[31] &= 127;
d[31] |= 64;
for (i = 0; i < 32; i++) o[i] = d[i];
for (i = 0; i < 64; i++) d[i] = 0;
return o;
}
function convertKeyPair(edKeyPair) {
var publicKey = convertPublicKey(edKeyPair.publicKey);
if (!publicKey) return null;
return {
publicKey: publicKey,
secretKey: convertSecretKey(edKeyPair.secretKey)
};
}
// return {
// convertPublicKey: convertPublicKey,
// convertSecretKey: convertSecretKey,
// convertKeyPair: convertKeyPair,
// };
export default {
convertPublicKey: convertPublicKey,
convertSecretKey: convertSecretKey,
convertKeyPair: convertKeyPair,
}
// }));

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,336 @@
// QORA
const TYPES = {
GENESIS_TRANSACTION: 1,
PAYMENT_TRANSACTION: 2,
REGISTER_NAME_TRANSACTION: 3,
UPDATE_NAME_TRANSACTION: 4,
SELL_NAME_TRANSACTION: 5,
CANCEL_SELL_NAME_TRANSACTION: 6,
BUY_NAME_TRANSACTION: 7,
CREATE_POLL_TRANSACTION: 8,
VOTE_ON_POLL_TRANSACTION: 9,
ARBITRARY_TRANSACTION: 10,
ISSUE_ASSET_TRANSACTION: 11,
TRANSFER_ASSET_TRANSACTION: 12,
CREATE_ORDER_TRANSACTION: 13,
CANCEL_ORDER_TRANSACTION: 14,
MULTI_PAYMENT_TRANSACTION: 15,
DEPLOY_AT_TRANSACTION: 16,
MESSAGE_TRANSACTION: 17
};
function getKeyPairFromSeed(seed, returnBase58)
{
if(typeof(seed) == "string") {
seed = new Uint8Array(Base58.decode(seed));
}
var keyPair = nacl.sign.keyPair.fromSeed(seed);
var base58privateKey = Base58.encode(keyPair.secretKey);
var base58publicKey = Base58.encode(keyPair.publicKey);
if(returnBase58) {
return {
privateKey: Base58.encode(keyPair.secretKey),
publicKey: Base58.encode(keyPair.publicKey)
};
} else {
return {
privateKey: keyPair.secretKey,
publicKey: keyPair.publicKey
};
}
}
function stringtoUTF8Array(message) {
if (typeof message == 'string') {
var s = unescape(encodeURIComponent(message)); // UTF-8
message = new Uint8Array(s.length);
for (var i = 0; i < s.length; i++) {
message[i] = s.charCodeAt(i) & 0xff;
}
}
return message;
}
function int32ToBytes (word) {
var byteArray = [];
for (var b = 0; b < 32; b += 8) {
byteArray.push((word >>> (24 - b % 32)) & 0xFF);
}
return byteArray;
}
function int64ToBytes (int64) {
// we want to represent the input as a 8-bytes array
var byteArray = [0, 0, 0, 0, 0, 0, 0, 0];
for ( var index = 0; index < byteArray.length; index ++ ) {
var byte = int64 & 0xff;
byteArray [ byteArray.length - index - 1 ] = byte;
int64 = (int64 - byte) / 256 ;
}
return byteArray;
}
function appendBuffer (buffer1, buffer2) {
buffer1 = new Uint8Array(buffer1);
buffer2 = new Uint8Array(buffer2);
var tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength);
tmp.set(buffer1, 0);
tmp.set(buffer2, buffer1.byteLength);
return tmp;
}
function equal (buf1, buf2)
{
if (buf1.byteLength != buf2.byteLength) return false;
var dv1 = new Uint8Array(buf1);
var dv2 = new Uint8Array(buf2);
for (var i = 0; i != buf1.byteLength; i++)
{
if (dv1[i] != dv2[i]) return false;
}
return true;
}
function generateAccountSeed(seed, nonce, returnBase58)
{
if(typeof(seed) == "string") {
seed = Base58.decode(seed);
}
nonceBytes = int32ToBytes(nonce);
var resultSeed = new Uint8Array();
resultSeed = appendBuffer(resultSeed, nonceBytes);
resultSeed = appendBuffer(resultSeed, seed);
resultSeed = appendBuffer(resultSeed, nonceBytes);
if(returnBase58) {
return Base58.encode(SHA256.digest(SHA256.digest(resultSeed)));
} else {
return new SHA256.digest(SHA256.digest(resultSeed));
}
}
function getAccountAddressFromPublicKey(publicKey)
{
var ADDRESS_VERSION = 58; // Q
if(typeof(publicKey) == "string") {
publicKey = Base58.decode(publicKey);
}
var publicKeyHashSHA256 = SHA256.digest(publicKey);
var ripemd160 = new RIPEMD160();
var publicKeyHash = ripemd160.digest(publicKeyHashSHA256);
var addressArray = new Uint8Array();
addressArray = appendBuffer(addressArray, [ADDRESS_VERSION]);
addressArray = appendBuffer(addressArray, publicKeyHash);
var checkSum = SHA256.digest(SHA256.digest(addressArray));
addressArray = appendBuffer(addressArray, checkSum.subarray(0, 4));
return Base58.encode(addressArray);
}
function getAccountAddressType(address)
{
try {
var ADDRESS_VERSION = 58; // Q
var AT_ADDRESS_VERSION = 23; // A
if(typeof(address) == "string") {
address = Base58.decode(address);
}
var checkSum = address.subarray(address.length - 4, address.length)
var addressWitoutChecksum = address.subarray(0, address.length - 4);
var checkSumTwo = SHA256.digest(SHA256.digest(addressWitoutChecksum));
checkSumTwo = checkSumTwo.subarray(0, 4);
if (equal(checkSum, checkSumTwo))
{
if(address[0] == ADDRESS_VERSION)
{
return "standard";
}
if(address[0] == AT_ADDRESS_VERSION)
{
return "at";
}
}
return "invalid";
} catch (e) {
return "invalid";
}
}
function isValidAddress(address)
{
return (getAccountAddressType(address) != "invalid");
}
function generateSignaturePaymentTransaction(keyPair, lastReference, recipient, amount, fee, timestamp) {
const data = generatePaymentTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp);
return nacl.sign.detached(data, keyPair.privateKey);
}
function generatePaymentTransaction(keyPair, lastReference, recipient, amount, fee, timestamp, signature) {
return appendBuffer(generatePaymentTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp),
signature);
}
function generatePaymentTransactionBase(publicKey, lastReference, recipient, amount, fee, timestamp) {
const txType = TYPES.PAYMENT_TRANSACTION;
const typeBytes = int32ToBytes(txType);
const timestampBytes = int64ToBytes(timestamp);
const amountBytes = int64ToBytes(amount * 100000000);
const feeBytes = int64ToBytes(fee * 100000000);
var data = new Uint8Array();
data = appendBuffer(data, typeBytes);
data = appendBuffer(data, timestampBytes);
data = appendBuffer(data, lastReference);
data = appendBuffer(data, publicKey);
data = appendBuffer(data, recipient);
data = appendBuffer(data, amountBytes);
data = appendBuffer(data, feeBytes);
return data;
}
function generateSignatureMessageTransaction(keyPair, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted) {
const data = generateMessageTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted);
return nacl.sign.detached(data, keyPair.privateKey);
}
function generateMessageTransaction(keyPair, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted, signature) {
return appendBuffer(generateMessageTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted),
signature);
}
function generateMessageTransactionBase(publicKey, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted) {
txType = TYPES.MESSAGE_TRANSACTION;
const typeBytes = int32ToBytes(txType);
const timestampBytes = int64ToBytes(timestamp);
const amountBytes = int64ToBytes(amount * 100000000);
const feeBytes = int64ToBytes(fee * 100000000);
const messageLength = int32ToBytes(message.length);
const key = int64ToBytes(0);
isTextB = new Uint8Array(1);
isTextB[0] = isText;
isEncryptedB = new Uint8Array(1);
isEncryptedB[0] = isEncrypted;
var data = new Uint8Array();
data = appendBuffer(data, typeBytes);
data = appendBuffer(data, timestampBytes);
data = appendBuffer(data, lastReference);
data = appendBuffer(data, publicKey);
data = appendBuffer(data, recipient);
data = appendBuffer(data, key);
data = appendBuffer(data, amountBytes);
data = appendBuffer(data, messageLength);
data = appendBuffer(data, message);
data = appendBuffer(data, isEncryptedB);
data = appendBuffer(data, isTextB);
data = appendBuffer(data, feeBytes);
return data;
}
function generateSignatureArbitraryTransactionV3(keyPair, lastReference, service, arbitraryData, fee, timestamp) {
const data = generateArbitraryTransactionV3Base(keyPair.publicKey, lastReference, service, arbitraryData, fee, timestamp);
return nacl.sign.detached(data, keyPair.privateKey);
}
function generateArbitraryTransactionV3(keyPair, lastReference, service, arbitraryData, fee, timestamp, signature) {
return appendBuffer(generateArbitraryTransactionV3Base(keyPair.publicKey, lastReference, service, arbitraryData, fee, timestamp),
signature);
}
function generateArbitraryTransactionV3Base(publicKey, lastReference, service, arbitraryData, fee, timestamp) {
const txType = TYPES.ARBITRARY_TRANSACTION;
const typeBytes = int32ToBytes(txType);
const timestampBytes = int64ToBytes(timestamp);
const feeBytes = int64ToBytes(fee * 100000000);
const serviceBytes = int32ToBytes(service);
const dataSizeBytes = int32ToBytes(arbitraryData.length);
const paymentsLengthBytes = int32ToBytes(0); // Support payments - not yet.
var data = new Uint8Array();
data = appendBuffer(data, typeBytes);
data = appendBuffer(data, timestampBytes);
data = appendBuffer(data, lastReference);
data = appendBuffer(data, publicKey);
data = appendBuffer(data, paymentsLengthBytes);
// Here it is necessary to insert the payments, if there are
data = appendBuffer(data, serviceBytes);
data = appendBuffer(data, dataSizeBytes);
data = appendBuffer(data, arbitraryData);
data = appendBuffer(data, feeBytes);
return data;
}
function generateSignatureRegisterNameTransaction(keyPair, lastReference, owner, name, value, fee, timestamp) {
const data = generateRegisterNameTransactionBase(keyPair.publicKey, lastReference, owner, name, value, fee, timestamp);
return nacl.sign.detached(data, keyPair.privateKey);
}
function generateRegisterNameTransaction(keyPair, lastReference, owner, name, value, fee, timestamp, signature) {
return appendBuffer( generateRegisterNameTransactionBase(keyPair.publicKey, lastReference, owner, name, value, fee, timestamp),
signature );
}
function generateRegisterNameTransactionBase(publicKey, lastReference, owner, name, value, fee, timestamp) {
const txType = TYPES.REGISTER_NAME_TRANSACTION;
const typeBytes = int32ToBytes(txType);
const timestampBytes = int64ToBytes(timestamp);
const feeBytes = int64ToBytes(fee * 100000000);
const nameSizeBytes = int32ToBytes(name.length);
const valueSizeBytes = int32ToBytes(value.length);
var data = new Uint8Array();
data = appendBuffer(data, typeBytes);
data = appendBuffer(data, timestampBytes);
data = appendBuffer(data, lastReference);
data = appendBuffer(data, publicKey);
data = appendBuffer(data, owner);
data = appendBuffer(data, nameSizeBytes);
data = appendBuffer(data, name);
data = appendBuffer(data, valueSizeBytes);
data = appendBuffer(data, value);
data = appendBuffer(data, feeBytes);
return data;
}

View File

@@ -0,0 +1,226 @@
// Extracted from https://github.com/crypto-browserify/ripemd160
const ARRAY16 = new Array(16);
const zl = initU8Array([
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
]);
const zr = initU8Array([
5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
]);
const sl = initU8Array([
11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
]);
const sr = initU8Array([
8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
]);
const hl = initU32Array([0x00000000, 0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xa953fd4e]);
const hr = initU32Array([0x50a28be6, 0x5c4dd124, 0x6d703ef3, 0x7a6d76e9, 0x00000000]);
function rotl(x, n) {
return (x << n) | (x >>> (32 - n));
}
function fn1(a, b, c, d, e, m, k, s) {
return (rotl((a + (b ^ c ^ d) + m + k) | 0, s) + e) | 0;
}
function fn2(a, b, c, d, e, m, k, s) {
return (rotl((a + ((b & c) | ((~b) & d)) + m + k) | 0, s) + e) | 0;
}
function fn3(a, b, c, d, e, m, k, s) {
return (rotl((a + ((b | (~c)) ^ d) + m + k) | 0, s) + e) | 0;
}
function fn4(a, b, c, d, e, m, k, s) {
return (rotl((a + ((b & d) | (c & (~d))) + m + k) | 0, s) + e) | 0;
}
function fn5(a, b, c, d, e, m, k, s) {
return (rotl((a + (b ^ (c | (~d))) + m + k) | 0, s) + e) | 0;
}
function readInt32LE(buffer, offset) {
offset >>>= 0;
return (buffer[offset])
| (buffer[offset + 1] << 8)
| (buffer[offset + 2] << 16)
| (buffer[offset + 3] << 24);
}
function writeUInt32LE(buffer, value, offset) {
value = +value;
offset >>>= 0;
buffer[offset + 3] = (value >>> 24);
buffer[offset + 2] = (value >>> 16);
buffer[offset + 1] = (value >>> 8);
buffer[offset] = (value & 0xff);
return offset + 4;
}
function writeInt32LE(buffer, value, offset) {
value = +value;
offset >>>= 0;
buffer[offset] = (value & 0xff);
buffer[offset + 1] = (value >>> 8);
buffer[offset + 2] = (value >>> 16);
buffer[offset + 3] = (value >>> 24);
return offset + 4;
}
function initU32Array(data) {
if (typeof Uint32Array !== 'undefined') {
return new Uint32Array(data);
}
else {
return data;
}
}
function initU8Array(data) {
if (typeof Uint8Array !== 'undefined') {
return new Uint8Array(data);
}
else {
return data;
}
}
function createU8Array(size) {
if (typeof Uint8Array !== 'undefined') {
return new Uint8Array(size);
}
else {
return new Array(size);
}
}
export class RIPEMD160 {
constructor() {
this._block = createU8Array(64);
this._blockSize = 64;
this._blockOffset = 0;
this._length = [0, 0, 0, 0];
this._finalized = false;
this._a = 0x67452301;
this._b = 0xefcdab89;
this._c = 0x98badcfe;
this._d = 0x10325476;
this._e = 0xc3d2e1f0;
}
update(data) {
if (this._finalized)
throw new Error('Digest already called');
// consume data
const block = this._block;
let offset = 0;
while (this._blockOffset + data.length - offset >= this._blockSize) {
for (let i = this._blockOffset; i < this._blockSize;)
block[i++] = data[offset++];
this._update();
this._blockOffset = 0;
}
while (offset < data.length)
block[this._blockOffset++] = data[offset++];
// update length
for (let j = 0, carry = data.length * 8; carry > 0; ++j) {
this._length[j] += carry;
carry = (this._length[j] / 0x0100000000) | 0;
if (carry > 0)
this._length[j] -= 0x0100000000 * carry;
}
return this;
}
_update() {
const words = ARRAY16;
for (let j = 0; j < 16; ++j) {
words[j] = readInt32LE(this._block, j * 4);
}
let al = this._a | 0;
let bl = this._b | 0;
let cl = this._c | 0;
let dl = this._d | 0;
let el = this._e | 0;
let ar = this._a | 0;
let br = this._b | 0;
let cr = this._c | 0;
let dr = this._d | 0;
let er = this._e | 0;
// computation
for (let i = 0; i < 80; i += 1) {
let tl;
let tr;
if (i < 16) {
tl = fn1(al, bl, cl, dl, el, words[zl[i]], hl[0], sl[i]);
tr = fn5(ar, br, cr, dr, er, words[zr[i]], hr[0], sr[i]);
}
else if (i < 32) {
tl = fn2(al, bl, cl, dl, el, words[zl[i]], hl[1], sl[i]);
tr = fn4(ar, br, cr, dr, er, words[zr[i]], hr[1], sr[i]);
}
else if (i < 48) {
tl = fn3(al, bl, cl, dl, el, words[zl[i]], hl[2], sl[i]);
tr = fn3(ar, br, cr, dr, er, words[zr[i]], hr[2], sr[i]);
}
else if (i < 64) {
tl = fn4(al, bl, cl, dl, el, words[zl[i]], hl[3], sl[i]);
tr = fn2(ar, br, cr, dr, er, words[zr[i]], hr[3], sr[i]);
}
else { // if (i<80) {
tl = fn5(al, bl, cl, dl, el, words[zl[i]], hl[4], sl[i]);
tr = fn1(ar, br, cr, dr, er, words[zr[i]], hr[4], sr[i]);
}
al = el;
el = dl;
dl = rotl(cl, 10);
cl = bl;
bl = tl;
ar = er;
er = dr;
dr = rotl(cr, 10);
cr = br;
br = tr;
}
// update state
const t = (this._b + cl + dr) | 0;
this._b = (this._c + dl + er) | 0;
this._c = (this._d + el + ar) | 0;
this._d = (this._e + al + br) | 0;
this._e = (this._a + bl + cr) | 0;
this._a = t;
}
digest() {
if (this._finalized) {
throw new Error('Digest already called');
}
this._finalized = true;
// create padding and handle blocks
this._block[this._blockOffset++] = 0x80;
if (this._blockOffset > 56) {
this._block.fill(0, this._blockOffset, 64);
this._update();
this._blockOffset = 0;
}
this._block.fill(0, this._blockOffset, 56);
writeUInt32LE(this._block, this._length[0], 56);
writeUInt32LE(this._block, this._length[1], 60);
this._update();
// produce result
const buffer = createU8Array(20);
writeInt32LE(buffer, this._a, 0);
writeInt32LE(buffer, this._b, 4);
writeInt32LE(buffer, this._c, 8);
writeInt32LE(buffer, this._d, 12);
writeInt32LE(buffer, this._e, 16);
// reset state
this._block.fill(0);
this._blockOffset = 0;
for (let i = 0; i < 4; ++i) {
this._length[i] = 0;
}
return buffer;
}
}
export default RIPEMD160;

View File

@@ -0,0 +1,142 @@
// SHA-256 hash function. Copyright-free.
// Requires typed arrays.
const SHA256 = {};
SHA256.K = [
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b,
0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01,
0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7,
0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152,
0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc,
0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819,
0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08,
0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f,
0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
];
// The digest function returns the hash value (digest)
// as a 32 byte (typed) array.
// message: the string or byte array to hash
SHA256.digest = function(message) {
var h0 = 0x6a09e667;
var h1 = 0xbb67ae85;
var h2 = 0x3c6ef372;
var h3 = 0xa54ff53a;
var h4 = 0x510e527f;
var h5 = 0x9b05688c;
var h6 = 0x1f83d9ab;
var h7 = 0x5be0cd19;
var K = SHA256.K;
if (typeof message == 'string') {
var s = unescape(encodeURIComponent(message)); // UTF-8
message = new Uint8Array(s.length);
for (var i = 0; i < s.length; i++) {
message[i] = s.charCodeAt(i) & 0xff;
}
}
var length = message.length;
var byteLength = Math.floor((length + 72) / 64) * 64;
var wordLength = byteLength / 4;
var bitLength = length * 8;
var m = new Uint8Array(byteLength);
m.set(message);
m[length] = 0x80;
m[byteLength - 4] = bitLength >>> 24;
m[byteLength - 3] = (bitLength >>> 16) & 0xff;
m[byteLength - 2] = (bitLength >>> 8) & 0xff;
m[byteLength - 1] = bitLength & 0xff;
var words = new Int32Array(wordLength);
var byteIndex = 0;
for (var i = 0; i < words.length; i++) {
var word = m[byteIndex++] << 24;
word |= m[byteIndex++] << 16;
word |= m[byteIndex++] << 8;
word |= m[byteIndex++];
words[i] = word;
}
var w = new Int32Array(64);
for (var j = 0; j < wordLength; j += 16) {
for (i = 0; i < 16; i++) {
w[i] = words[j + i];
}
for (i = 16; i < 64; i++) {
var v = w[i - 15];
var s0 = (v >>> 7) | (v << 25);
s0 ^= (v >>> 18) | (v << 14);
s0 ^= (v >>> 3);
v = w[i - 2];
var s1 = (v >>> 17) | (v << 15);
s1 ^= (v >>> 19) | (v << 13);
s1 ^= (v >>> 10);
w[i] = (w[i - 16] + s0 + w[i - 7] + s1) & 0xffffffff;
}
var a = h0;
var b = h1;
var c = h2;
var d = h3;
var e = h4;
var f = h5;
var g = h6;
var h = h7;
for (i = 0; i < 64; i++) {
s1 = (e >>> 6) | (e << 26);
s1 ^= (e >>> 11) | (e << 21);
s1 ^= (e >>> 25) | (e << 7);
var ch = (e & f) ^ (~e & g);
var temp1 = (h + s1 + ch + K[i] + w[i]) & 0xffffffff;
s0 = (a >>> 2) | (a << 30);
s0 ^= (a >>> 13) | (a << 19);
s0 ^= (a >>> 22) | (a << 10);
var maj = (a & b) ^ (a & c) ^ (b & c);
var temp2 = (s0 + maj) & 0xffffffff;
h = g
g = f
f = e
e = (d + temp1) & 0xffffffff;
d = c;
c = b;
b = a;
a = (temp1 + temp2) & 0xffffffff;
}
h0 = (h0 + a) & 0xffffffff;
h1 = (h1 + b) & 0xffffffff;
h2 = (h2 + c) & 0xffffffff;
h3 = (h3 + d) & 0xffffffff;
h4 = (h4 + e) & 0xffffffff;
h5 = (h5 + f) & 0xffffffff;
h6 = (h6 + g) & 0xffffffff;
h7 = (h7 + h) & 0xffffffff;
}
var hash = new Uint8Array(32);
for (var i = 0; i < 4; i++) {
hash[i] = (h0 >>> (8 * (3 - i))) & 0xff;
hash[i + 4] = (h1 >>> (8 * (3 - i))) & 0xff;
hash[i + 8] = (h2 >>> (8 * (3 - i))) & 0xff;
hash[i + 12] = (h3 >>> (8 * (3 - i))) & 0xff;
hash[i + 16] = (h4 >>> (8 * (3 - i))) & 0xff;
hash[i + 20] = (h5 >>> (8 * (3 - i))) & 0xff;
hash[i + 24] = (h6 >>> (8 * (3 - i))) & 0xff;
hash[i + 28] = (h7 >>> (8 * (3 - i))) & 0xff;
}
return hash;
}
// The hash function returns the hash value as a hex string.
// message: the string or byte array to hash
SHA256.hash = function(message) {
var digest = SHA256.digest(message);
var hex = '';
for (var i = 0; i < digest.length; i++) {
var s = '0' + digest[i].toString(16);
hex += s.length > 2 ? s.substring(1) : s;
}
return hex;
}
// == Convert to ES6 Module == //
export default SHA256;

View File

@@ -0,0 +1,74 @@
'use strict'
const utils = {
int32ToBytes(word) {
var byteArray = []
for (var b = 0; b < 32; b += 8) {
byteArray.push((word >>> (24 - b % 32)) & 0xFF)
}
return byteArray
},
stringtoUTF8Array(message) {
if (typeof message === 'string') {
var s = unescape(encodeURIComponent(message)) // UTF-8
message = new Uint8Array(s.length)
for (var i = 0; i < s.length; i++) {
message[i] = s.charCodeAt(i) & 0xff
}
}
return message
},
// ...buffers then buffers.foreach and append to buffer1
appendBuffer(buffer1, buffer2) {
buffer1 = new Uint8Array(buffer1)
buffer2 = new Uint8Array(buffer2)
let tmp = new Uint8Array(buffer1.byteLength + buffer2.byteLength)
tmp.set(buffer1, 0)
tmp.set(buffer2, buffer1.byteLength)
return tmp
},
int64ToBytes(int64) {
// we want to represent the input as a 8-bytes array
var byteArray = [0, 0, 0, 0, 0, 0, 0, 0]
for (var index = 0; index < byteArray.length; index++) {
var byte = int64 & 0xff
byteArray[byteArray.length - index - 1] = byte
int64 = (int64 - byte) / 256
}
return byteArray
},
hexToBytes(hexString) {
return new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)))
},
stringToHex(bytes) {
return bytes.reduce((str, byte) => str + byte.toString(16).padStart(2, '0'), '')
},
equal(buf1, buf2) {
if (buf1.byteLength != buf2.byteLength) return false
var dv1 = new Uint8Array(buf1)
var dv2 = new Uint8Array(buf2)
for (var i = 0; i != buf1.byteLength; i++) {
if (dv1[i] != dv2[i]) return false
}
return true
},
bytesToHex(byteArray) {
var _byteArrayToHex = []
for (var index = 0; index < byteArray.length; index++) {
_byteArrayToHex.push((byteArray[index] >>> 4).toString(16))
_byteArrayToHex.push((byteArray[index] & 15).toString(16));
}
return _byteArrayToHex.join("")
}
}
export default utils

View File

@@ -0,0 +1,30 @@
import { watchConfig, waitForConfig } from '../config.js'
let config = {}
watchConfig((c) => {
config = c
})
export async function request(url, options) {
options = options || {}
const body = options.body
const method = options.method || 'GET'
const headers = options.headers || {}
await waitForConfig()
const n = config.nodeConfig.knownNodes[config.nodeConfig.node]
const node = n.protocol + '://' + n.domain + ':' + n.port
return fetch(node + url, {
method,
headers,
body,
}).then(async (response) => {
try {
const json = await response.clone().json()
return json
} catch (e) {
return await response.text()
}
})
}

View File

@@ -0,0 +1,39 @@
import { store } from '../api_deps.js'
import { stateAwait } from './utils/stateAwait.js'
import { Sha512 } from 'asmcrypto.js'
import utils from '../api/deps/utils.js'
export const kdf = async (seed, salt, status = () => { }) => {
const state = store.getState()
const config = state.config
const workers = state.app.workers.workers
status('Waiting for workers to be ready')
await stateAwait(state => state.app.workers.ready)
status('Deriving key parts')
salt = new Uint8Array(salt)
const seedParts = await Promise.all(workers.map((worker, index) => {
const nonce = index
return worker.request('kdf', {
key: seed,
salt,
nonce,
staticSalt: config.crypto.staticSalt,
staticBcryptSalt: config.crypto.staticBcryptSalt
}).then(data => {
let jsonData
try {
jsonData = JSON.parse(data)
data = jsonData
} catch (e) {
// ...
}
if (seed !== data.key) throw new Error('Error, incorrect key. ' + seed + ' !== ' + data.key)
if (nonce !== data.nonce) throw new Error('Error, incorrect nonce')
return data.result
})
}))
status('Combining key parts')
const result = new Sha512().process(utils.stringtoUTF8Array(config.crypto.staticSalt + seedParts.reduce((a, c) => a + c))).finish().result
status('Key is ready ')
return result
}

View File

@@ -0,0 +1,46 @@
/**
* Not to be confused with register name...this is a special use case
*/
import { request, createTransaction, processTransaction } from './api.js'
const TX_TYPE = 3 // NAME_REGISTRATION
const CHECK_LAST_REF_INTERVAL = 30 * 1000 // err 30 seconds
const pendingAddresses = {}
// const config = store.getState().config
// const node = config.coin.node.api
// const baseUrl = node.url + node.tail
const checkLastRefs = () => {
Object.entries(pendingAddresses).forEach(([address, fn]) => {
// console.log(fn, address)
request('addresses/lastreference/' + address).then(res => {
if (res === 'false') return
fn(res)
delete pendingAddresses[address]
clearInterval(lastRefInterval)
})
// fetch(baseUrl + 'addresses/lastreference/' + address)
// .then(async res => res.text())
})
}
const lastRefInterval = setInterval(() => checkLastRefs(), CHECK_LAST_REF_INTERVAL)
const callOnLastRef = (address, fn) => {
pendingAddresses[address] = fn
}
export const registerUsername = async ({ name, address, lastRef, keyPair }) => {
callOnLastRef(address, lastreference => {
const txBytes = createTransaction(TX_TYPE, keyPair, {
registrantPublicKey: keyPair.publicKey,
registrantAddress: address,
name,
value: address,
lastReference: lastreference
})
processTransaction(txBytes).then(res => {})
})
}

View File

@@ -0,0 +1,33 @@
import { HmacSha512, AES_CBC } from 'asmcrypto.js'
import { kdf } from './kdf.js'
// import Base58 from '../qora/deps/Base58.js'
import Base58 from './deps/Base58.js'
const getRandomValues = window.crypto ? window.crypto.getRandomValues.bind(window.crypto) : window.msCrypto.getRandomValues.bind(window.msCrypto)
export const generateSaveWalletData = async (wallet, password, kdfThreads, statusUpdateFn) => {
statusUpdateFn('Generating random values')
let iv = new Uint8Array(16)
getRandomValues(iv)
let salt = new Uint8Array(32)
getRandomValues(salt) // Can actually use a salt this time, as we can store the salt with the wallet
// const key = PBKDF2_HMAC_SHA512.bytes(utils.stringtoUTF8Array(password), salt, PBKDF2_ROUNDS, 64) // 512bit key to be split in two for mac/encryption
const key = await kdf(password, salt, statusUpdateFn)
statusUpdateFn('Encrypting seed')
const encryptionKey = key.slice(0, 32)
const macKey = key.slice(32, 63)
const encryptedSeed = AES_CBC.encrypt(wallet._byteSeed, encryptionKey, false, iv)
// const mac = HmacSha512.bytes(encryptedSeed, macKey)
statusUpdateFn('Generating mac')
const mac = new HmacSha512(macKey).process(encryptedSeed).finish().result
return {
address0: wallet._addresses[0].address,
encryptedSeed: Base58.encode(encryptedSeed),
salt: Base58.encode(salt),
iv: Base58.encode(iv),
version: wallet._walletVersion,
mac: Base58.encode(mac),
kdfThreads
}
}

View File

@@ -0,0 +1,97 @@
// Trade Bot
import TradeBotCreateRequest from './transactions/trade-portal/tradebot/TradeBotCreateRequest.js';
import TradeBotRespondRequest from './transactions/trade-portal/tradebot/TradeBotRespondRequest.js';
import signTradeBotTransaction from './transactions/trade-portal/tradebot/signTradeBotTransaction.js'
// Trade Offer
import DeleteTradeOffer from './transactions/trade-portal/tradeoffer/DeleteTradeOffer.js';
import { request } from './fetch-request'
// TradeBotCreateRequest
export const tradeBotCreateRequest = (requestObject) => {
const txn = new TradeBotCreateRequest().createTransaction(requestObject)
return request('/crosschain/tradebot/create', {
method: 'POST',
headers: {
'Accept': 'text/plain',
'Content-Type': 'application/json'
},
body: JSON.stringify(txn)
})
}
// TradeBotRespondRequest
export const tradeBotRespondRequest = (requestObject) => {
const txn = new TradeBotRespondRequest().createTransaction(requestObject)
return request('/crosschain/tradebot/respond', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(txn)
})
}
// Sign Trade Transactions
export const signTradeBotTxn = (unsignedTxn, keyPair) => {
return signTradeBotTransaction(unsignedTxn, keyPair)
}
// Delete Trade Offer
export const deleteTradeOffer = (requestObject) => {
const txn = new DeleteTradeOffer().createTransaction(requestObject)
return request('/crosschain/tradeoffer', {
method: 'DELETE',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(txn)
})
}
// Send BTC
export const sendBtc = (requestObject) => {
return request('/crosschain/btc/send', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(requestObject)
})
}
// Send LTC
export const sendLtc = (requestObject) => {
return request('/crosschain/ltc/send', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(requestObject)
})
}
// Send DOGE
export const sendDoge = (requestObject) => {
return request('/crosschain/doge/send', {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(requestObject)
})
}

View File

@@ -0,0 +1,50 @@
'use strict';
import TransactionBase from './TransactionBase.js'
import { QORT_DECIMALS } from '../constants.js'
// import { Sha256 } from 'asmcrypto.js/dist_es5/entry-export_all.js'
export default class PaymentTransaction extends TransactionBase {
constructor () {
super()
this.type = 20
this.amount = 42 * Math.pow(10, 8)
this.tests.push(
() => {
if (!(this._amount >= 0)) {
return 'Invalid amount ' + this._amount / QORT_DECIMALS
}
return true
},
() => {
if (!(this._recipient instanceof Uint8Array && this._recipient.length == 25)) {
return 'Invalid recipient ' + Base58.encode(this._recipient)
}
return true
}
)
}
set recipient (recipient) { // Always Base58 encoded. Accepts Uint8Array or Base58 string.
this._recipient = recipient instanceof Uint8Array ? recipient : this.constructor.Base58.decode(recipient)
}
set amount (amount) {
this._amount = amount * QORT_DECIMALS
this._amountBytes = this.constructor.utils.int64ToBytes(amount)
}
set reference (seed) {
const sha = seed => new Sha512().process(seed).finish().result
let reference = sha(sha(seed))
reference += reference
}
get params () {
const params = super.params
params.push(
this._recipient,
this._amountBytes,
this._feeBytes
)
return params
}
}

View File

@@ -0,0 +1,31 @@
'use strict';
import TransactionBase from './TransactionBase.js'
// import { QORT_DECIMALS } from "../constants.js" // Not needed, no amount
export default class DelegationTransaction extends TransactionBase {
constructor () {
super()
this.type = 18
this.tests.push(
() => {
if (!(this._superNodeAddress instanceof Uint8Array && this._superNodeAddress.length == 25)) {
return 'Invalid recipient ' + Base58.encode(this._superNodeAddress)
}
return true
}
)
}
set superNodeAddress (superNodeAddress) { // Always Base58 encoded. Accepts Uint8Array or Base58 string.
this._superNodeAddress = superNodeAddress instanceof Uint8Array ? superNodeAddress : this.constructor.Base58.decode(superNodeAddress)
}
get params () {
const params = super.params
params.push(
this._superNodeAddress,
this._feeBytes
)
return params
}
}

View File

@@ -0,0 +1,95 @@
"use strict";
import PaymentTransaction from "./PaymentTransaction.js"
import { QORT_DECIMALS } from "../constants.js"
/* ====================================
EXTEND THE PAYMENT TRANSACTION YOU CLOWN
====================================== */
export default class MessageTransaction extends PaymentTransaction{
constructor(){
super();
this.type = 17
this._key = this.constructor.utils.int64ToBytes(0);
this._isEncrypted = new Uint8Array(1); // Defaults to false
this._isText = new Uint8Array(1); // Defaults to false
}
set message(message /* UTF8 String */){
// ...yes? no?
this.messageText = message;
// Not sure about encoding here...
//this._message = message instanceof Uint8Array ? message : this.constructor.Base58.decode(message);
this._message = this.constructor.utils.stringtoUTF8Array(message)
this._messageLength = this.constructor.utils.int64ToBytes(this._message.length)
}
set isEncrypted(isEncrypted){
this._isEncrypted[0] = isEncrypted;
}
set isText(isText){
this._isText[0] = isText;
}
get _params(){
// dont extend super because paymentTrasaction is different
//const params = super.params;
return [
this._typeBytes,
this._timestampBytes,
this._lastReference,
this._keyPair.publicKey,
this._recipient,
this._key,
this._amountBytes,
this._messageLength,
this._message,
this._isEncrypted,
this._isText,
this._feeBytes
]
}
}
//"use strict";
//function generateSignatureMessageTransaction(keyPair, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted) => {
// const data = generateMessageTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted);
// return nacl.sign.detached(data, keyPair.privateKey);
//}
//
//function generateMessageTransaction(keyPair, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted, signature) => {
// return appendBuffer(generateMessageTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted),
// signature);
//}
//function generateMessageTransactionBase(publicKey, lastReference, recipient, amount, fee, timestamp, message, isText, isEncrypted) => {
// txType = TYPES.MESSAGE_TRANSACTION;
//
// const typeBytes = int32ToBytes(txType);
// const timestampBytes = int64ToBytes(timestamp);
// const amountBytes = int64ToBytes(amount * 100000000);
// const feeBytes = int64ToBytes(fee * 100000000);
// const messageLength = int32ToBytes(message.length);
// const key = int64ToBytes(0);
//
// isTextB = new Uint8Array(1);
// isTextB[0] = isText;
//
// isEncryptedB = new Uint8Array(1);
// isEncryptedB[0] = isEncrypted;
//
// let data = new Uint8Array();
//
// data = appendBuffer(data, typeBytes);
// data = appendBuffer(data, timestampBytes);
// data = appendBuffer(data, lastReference);
// data = appendBuffer(data, publicKey);
// data = appendBuffer(data, recipient);
// data = appendBuffer(data, key);
// data = appendBuffer(data, amountBytes);
// data = appendBuffer(data, messageLength);
// data = appendBuffer(data, message);
// data = appendBuffer(data, isEncryptedB);
// data = appendBuffer(data, isTextB);
// data = appendBuffer(data, feeBytes);
//
// return data;
//}

View File

@@ -0,0 +1,96 @@
'use strict';
import TransactionBase from './TransactionBase.js'
// import { QORT_DECIMALS } from '../constants.js'
import Base58 from '../deps/Base58.js'
// import { store } from '../../store.js'
import { store } from '../../api.js'
export default class PaymentTransaction extends TransactionBase {
constructor() {
super()
this.type = 2
this.tests.push(
() => {
if (!(this._amount >= 0)) {
return 'Invalid amount ' + this._amount / store.getState().config.coin.decimals
}
return true
},
() => {
if (!(this._recipient instanceof Uint8Array && this._recipient.length == 25)) {
return 'Invalid recipient ' + Base58.encode(this._recipient)
}
return true
}
)
}
set recipient(recipient) { // Always Base58 encoded. Accepts Uint8Array or Base58 string.
this._recipient = recipient instanceof Uint8Array ? recipient : this.constructor.Base58.decode(recipient)
}
set amount(amount) {
// console.log('=====DECIMALS ', store.getState().config.coin.decimals)
// console.log("IINIT AMOUNT: ", amount);
this._amount = amount * store.getState().config.coin.decimals
this._amountBytes = this.constructor.utils.int64ToBytes(this._amount)
}
get params() {
const params = super.params
params.push(
this._recipient,
this._amountBytes,
this._feeBytes
)
return params
}
render(html) {
const conf = store.getState().config
// console.log(this)
return html`
<table>
<tr>
<th>To</th>
<td>${Base58.encode(this._recipient)}</td>
</tr>
<tr>
<th>Amount</th>
<td>${this._amount / conf.coin.decimals} ${conf.coin.symbol}</td>
</tr>
</table>
`
}
}
//
// import txTypes from "./txTypes.js"
// import nacl from "./deps/nacl-fast.js"
// import Utils from "./Utils.js"
//
// function generateSignaturePaymentTransaction(keyPair, lastReference, recipient, amount, fee, timestamp) => {
// const data = generatePaymentTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp);
// return nacl.sign.detached(data, keyPair.privateKey);
// }
//
// function generatePaymentTransaction(keyPair, lastReference, recipient, amount, fee, timestamp, signature) => {
// return Utils.appendBuffer(generatePaymentTransactionBase(keyPair.publicKey, lastReference, recipient, amount, fee, timestamp),signature);
// }
//
// function generatePaymentTransactionBase(publicKey, lastReference, recipient, amount, fee, timestamp) => {
// const txType = txTypes.PAYMENT_TRANSACTION;
// const typeBytes = Utils.int32ToBytes(txType);
// const timestampBytes = Utils.int64ToBytes(timestamp);
// const amountBytes = Utils.int64ToBytes(amount * 100000000);
// const feeBytes = Utils.int64ToBytes(fee * 100000000);
//
// let data = new Uint8Array();
//
// data = Utils.appendBuffer(data, typeBytes);
// data = Utils.appendBuffer(data, timestampBytes);
// data = Utils.appendBuffer(data, lastReference);
// data = Utils.appendBuffer(data, publicKey);
// data = Utils.appendBuffer(data, recipient);
// data = Utils.appendBuffer(data, amountBytes);
// data = Utils.appendBuffer(data, feeBytes);
//
// return data;
// }

View File

@@ -0,0 +1,23 @@
"use strict";
import ChatBase from "./chat/ChatBase.js"
export default class PublicizeTransaction extends ChatBase {
constructor() {
super();
this.type = 19
this.fee = 0
}
set proofOfWorkNonce(proofOfWorkNonce) {
this._proofOfWorkNonce = this.constructor.utils.int32ToBytes(proofOfWorkNonce)
}
get params() {
const params = super.params;
params.push(
this._proofOfWorkNonce,
this._feeBytes
)
return params;
}
}

View File

@@ -0,0 +1,162 @@
'use strict';
import { TX_TYPES, QORT_DECIMALS } from '../constants.js'
import nacl from '../deps/nacl-fast.js'
import Base58 from '../deps/Base58.js'
import utils from '../deps/utils.js'
export default class TransactionBase {
static get utils() {
return utils
}
static get nacl() {
return nacl
}
static get Base58() {
return Base58
}
constructor() {
// Defaults
this.fee = 0
this.groupID = 0
this.timestamp = Date.now()
this.tests = [
() => {
if (!(this._type >= 1 && this._type in TX_TYPES)) {
return 'Invalid type: ' + this.type
}
return true
},
() => {
if (this._fee < 0) {
return 'Invalid fee: ' + this._fee / QORT_DECIMALS
}
return true
},
() => {
if (this._groupID < 0 || !Number.isInteger(this._groupID)) {
return 'Invalid groupID: ' + this._groupID
}
return true
},
() => {
if (!(new Date(this._timestamp)).getTime() > 0) {
return 'Invalid timestamp: ' + this._timestamp
}
return true
},
() => {
if (!(this._lastReference instanceof Uint8Array && this._lastReference.byteLength == 64)) {
return 'Invalid last reference: ' + this._lastReference
}
return true
},
() => {
if (!(this._keyPair)) {
return 'keyPair must be specified'
}
if (!(this._keyPair.publicKey instanceof Uint8Array && this._keyPair.publicKey.byteLength === 32)) {
return 'Invalid publicKey'
}
if (!(this._keyPair.privateKey instanceof Uint8Array && this._keyPair.privateKey.byteLength === 64)) {
return 'Invalid privateKey'
}
return true
}
]
}
set keyPair(keyPair) {
this._keyPair = keyPair
}
set type(type) {
this.typeText = TX_TYPES[type]
this._type = type
this._typeBytes = this.constructor.utils.int32ToBytes(this._type)
}
set groupID(groupID) {
this._groupID = groupID
this._groupIDBytes = this.constructor.utils.int32ToBytes(this._groupID)
}
set timestamp(timestamp) {
this._timestamp = timestamp
this._timestampBytes = this.constructor.utils.int64ToBytes(this._timestamp)
}
set fee(fee) {
this._fee = fee * QORT_DECIMALS
this._feeBytes = this.constructor.utils.int64ToBytes(this._fee)
}
set lastReference(lastReference) { // Always Base58 encoded. Accepts Uint8Array or Base58 string.
// lastReference could be a string or an Uint8Array
this._lastReference = lastReference instanceof Uint8Array ? lastReference : this.constructor.Base58.decode(lastReference)
}
get params() {
return [
this._typeBytes,
this._timestampBytes,
this._groupIDBytes,
this._lastReference,
this._keyPair.publicKey
]
}
get signedBytes() {
if (!this._signedBytes) {
this.sign()
}
return this._signedBytes
}
// render function but NOT lit element
render(html) {
return html`render method to display requested transaction info`
}
validParams() {
let finalResult = {
valid: true
}
// const valid =
this.tests.some(test => {
const result = test()
if (result !== true) {
finalResult = {
valid: false,
message: result
}
return true // exists the loop
}
})
return finalResult
}
generateBase() {
const isValid = this.validParams()
if (!isValid.valid) {
throw new Error(isValid.message)
}
let result = new Uint8Array()
this.params.forEach(item => {
result = this.constructor.utils.appendBuffer(result, item)
})
this._base = result
return result
}
sign() {
if (!this._keyPair) {
throw new Error('keyPair not defined')
}
if (!this._base) {
this.generateBase()
}
this._signature = this.constructor.nacl.sign.detached(this._base, this._keyPair.privateKey)
this._signedBytes = this.constructor.utils.appendBuffer(this._base, this._signature)
return this._signature
}
}

View File

@@ -0,0 +1,42 @@
"use strict";
/*
TO DO
*/
(function(){
function generateSignatureArbitraryTransactionV3(keyPair, lastReference, service, arbitraryData, fee, timestamp) => {
const data = generateArbitraryTransactionV3Base(keyPair.publicKey, lastReference, service, arbitraryData, fee, timestamp);
return nacl.sign.detached(data, keyPair.privateKey);
}
function generateArbitraryTransactionV3(keyPair, lastReference, service, arbitraryData, fee, timestamp, signature) => {
return appendBuffer(generateArbitraryTransactionV3Base(keyPair.publicKey, lastReference, service, arbitraryData, fee, timestamp),
signature);
}
function generateArbitraryTransactionV3Base(publicKey, lastReference, service, arbitraryData, fee, timestamp) => {
const txType = TYPES.ARBITRARY_TRANSACTION;
const typeBytes = int32ToBytes(txType);
const timestampBytes = int64ToBytes(timestamp);
const feeBytes = int64ToBytes(fee * 100000000);
const serviceBytes = int32ToBytes(service);
const dataSizeBytes = int32ToBytes(arbitraryData.length);
const paymentsLengthBytes = int32ToBytes(0); // Support payments - not yet.
var data = new Uint8Array();
data = appendBuffer(data, typeBytes);
data = appendBuffer(data, timestampBytes);
data = appendBuffer(data, lastReference);
data = appendBuffer(data, publicKey);
data = appendBuffer(data, paymentsLengthBytes);
// Here it is necessary to insert the payments, if there are
data = appendBuffer(data, serviceBytes);
data = appendBuffer(data, dataSizeBytes);
data = appendBuffer(data, arbitraryData);
data = appendBuffer(data, feeBytes);
return data;
}
}())

View File

@@ -0,0 +1,137 @@
'use strict';
import { TX_TYPES, QORT_DECIMALS } from '../../constants.js'
import nacl from '../../deps/nacl-fast.js'
import Base58 from '../../deps/Base58.js'
import utils from '../../deps/utils.js'
export default class ChatBase {
static get utils() {
return utils
}
static get nacl() {
return nacl
}
static get Base58() {
return Base58
}
constructor() {
this.fee = 0
this.groupID = 0
this.tests = [
() => {
if (!(this._type >= 1 && this._type in TX_TYPES)) {
return 'Invalid type: ' + this.type
}
return true
},
() => {
if (this._fee < 0) {
return 'Invalid fee: ' + this._fee / QORT_DECIMALS
}
return true
},
() => {
if (this._groupID < 0 || !Number.isInteger(this._groupID)) {
return 'Invalid groupID: ' + this._groupID
}
return true
},
() => {
if (!(new Date(this._timestamp)).getTime() > 0) {
return 'Invalid timestamp: ' + this._timestamp
}
return true
},
() => {
if (!(this._lastReference instanceof Uint8Array && this._lastReference.byteLength == 64)) {
return 'Invalid last reference: ' + this._lastReference
}
return true
},
() => {
if (!(this._keyPair)) {
return 'keyPair must be specified'
}
if (!(this._keyPair.publicKey instanceof Uint8Array && this._keyPair.publicKey.byteLength === 32)) {
return 'Invalid publicKey'
}
if (!(this._keyPair.privateKey instanceof Uint8Array && this._keyPair.privateKey.byteLength === 64)) {
return 'Invalid privateKey'
}
return true
}
]
}
set keyPair(keyPair) {
this._keyPair = keyPair
}
set type(type) {
this.typeText = TX_TYPES[type]
this._type = type
this._typeBytes = this.constructor.utils.int32ToBytes(this._type)
}
set groupID(groupID) {
this._groupID = groupID
this._groupIDBytes = this.constructor.utils.int32ToBytes(this._groupID)
}
set timestamp(timestamp) {
this._timestamp = timestamp
this._timestampBytes = this.constructor.utils.int64ToBytes(this._timestamp)
}
set fee(fee) {
this._fee = fee * QORT_DECIMALS
this._feeBytes = this.constructor.utils.int64ToBytes(this._fee)
}
set lastReference(lastReference) {
this._lastReference = lastReference instanceof Uint8Array ? lastReference : this.constructor.Base58.decode(lastReference)
}
get params() {
return [
this._typeBytes,
this._timestampBytes,
this._groupIDBytes,
this._lastReference,
this._keyPair.publicKey
]
}
get chatBytes() {
const isValid = this.validParams()
if (!isValid.valid) {
throw new Error(isValid.message)
}
let result = new Uint8Array()
this.params.forEach(item => {
result = this.constructor.utils.appendBuffer(result, item)
})
this._chatBytes = result
return this._chatBytes
}
validParams() {
let finalResult = {
valid: true
}
this.tests.some(test => {
const result = test()
if (result !== true) {
finalResult = {
valid: false,
message: result
}
return true
}
})
return finalResult
}
}

View File

@@ -0,0 +1,77 @@
"use strict";
import ChatBase from "./ChatBase.js"
import nacl from '../../deps/nacl-fast.js'
import ed2curve from '../../deps/ed2curve.js'
import { Sha256 } from 'asmcrypto.js'
export default class ChatTransaction extends ChatBase {
constructor() {
super();
this.type = 18
this.fee = 0
}
set recipientPublicKey(recipientPublicKey) {
this._base58RecipientPublicKey = recipientPublicKey instanceof Uint8Array ? this.constructor.Base58.encode(recipientPublicKey) : recipientPublicKey
this._recipientPublicKey = this.constructor.Base58.decode(this._base58RecipientPublicKey)
}
set proofOfWorkNonce(proofOfWorkNonce) {
this._proofOfWorkNonce = this.constructor.utils.int32ToBytes(proofOfWorkNonce)
}
set recipient(recipient) {
this._recipient = recipient instanceof Uint8Array ? recipient : this.constructor.Base58.decode(recipient)
this._hasReceipient = new Uint8Array(1)
this._hasReceipient[0] = 1
}
set message(message) {
this.messageText = message;
this._message = this.constructor.utils.stringtoUTF8Array(message)
this._messageLength = this.constructor.utils.int32ToBytes(this._message.length)
}
set isEncrypted(isEncrypted) {
this._isEncrypted = new Uint8Array(1);
this._isEncrypted[0] = isEncrypted;
if (isEncrypted === 1) {
const convertedPrivateKey = ed2curve.convertSecretKey(this._keyPair.privateKey)
const convertedPublicKey = ed2curve.convertPublicKey(this._recipientPublicKey)
const sharedSecret = new Uint8Array(32);
nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey);
this._chatEncryptionSeed = new Sha256().process(sharedSecret).finish().result
this._encryptedMessage = nacl.secretbox(this._message, this._lastReference.slice(0, 24), this._chatEncryptionSeed)
}
this._myMessage = isEncrypted === 1 ? this._encryptedMessage : this._message
this._myMessageLenth = isEncrypted === 1 ? this.constructor.utils.int32ToBytes(this._myMessage.length) : this._messageLength
}
set isText(isText) {
this._isText = new Uint8Array(1);
this._isText[0] = isText;
}
get params() {
const params = super.params;
params.push(
this._proofOfWorkNonce,
this._hasReceipient,
this._recipient,
this._myMessageLenth,
this._myMessage,
this._isEncrypted,
this._isText,
this._feeBytes
)
return params;
}
}

View File

@@ -0,0 +1,52 @@
"use strict";
import ChatBase from "./ChatBase.js"
export default class GroupChatTransaction extends ChatBase {
constructor() {
super();
this.type = 18
this.fee = 0
}
set proofOfWorkNonce(proofOfWorkNonce) {
this._proofOfWorkNonce = this.constructor.utils.int32ToBytes(proofOfWorkNonce)
}
set hasReceipient(hasReceipient) {
this._hasReceipient = new Uint8Array(1)
this._hasReceipient[0] = hasReceipient
}
set message(message) {
this.messageText = message;
this._message = this.constructor.utils.stringtoUTF8Array(message)
this._messageLength = this.constructor.utils.int32ToBytes(this._message.length)
}
set isEncrypted(isEncrypted) {
this._isEncrypted = new Uint8Array(1);
this._isEncrypted[0] = isEncrypted; // Set to false...
}
set isText(isText) {
this._isText = new Uint8Array(1);
this._isText[0] = isText; // Set to true
}
get params() {
const params = super.params;
params.push(
this._proofOfWorkNonce,
this._hasReceipient,
this._messageLength,
this._message,
this._isEncrypted,
this._isText,
this._feeBytes
)
return params;
}
}

View File

@@ -0,0 +1,27 @@
import nacl from '../../deps/nacl-fast.js'
import Base58 from '../../deps/Base58.js'
import ed2curve from '../../deps/ed2curve.js'
import { Sha256 } from 'asmcrypto.js'
export const decryptChatMessage = (encryptedMessage, privateKey, recipientPublicKey, lastReference) => {
let _encryptedMessage = Base58.decode(encryptedMessage)
const _base58RecipientPublicKey = recipientPublicKey instanceof Uint8Array ? Base58.encode(recipientPublicKey) : recipientPublicKey
const _recipientPublicKey = Base58.decode(_base58RecipientPublicKey)
const _lastReference = lastReference instanceof Uint8Array ? lastReference : Base58.decode(lastReference)
const convertedPrivateKey = ed2curve.convertSecretKey(privateKey)
const convertedPublicKey = ed2curve.convertPublicKey(_recipientPublicKey)
const sharedSecret = new Uint8Array(32);
nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey);
const _chatEncryptionSeed = new Sha256().process(sharedSecret).finish().result
const _decryptedMessage = nacl.secretbox.open(_encryptedMessage, _lastReference.slice(0, 24), _chatEncryptionSeed)
let decryptedMessage = ''
_decryptedMessage === false ? decryptedMessage : decryptedMessage = new TextDecoder('utf-8').decode(_decryptedMessage);
return decryptedMessage
}

View File

@@ -0,0 +1,46 @@
import nacl from '../../deps/nacl-fast.js'
import utils from '../../deps/utils.js'
const signChat = (chatBytes, nonce, keyPair) => {
if (!chatBytes) {
throw new Error('Chat Bytes not defined')
}
if (!nonce) {
throw new Error('Nonce not defined')
}
if (!keyPair) {
throw new Error('keyPair not defined')
}
const _nonce = utils.int32ToBytes(nonce)
if (chatBytes.length === undefined) {
const _chatBytesBuffer = Object.keys(chatBytes).map(function (key) { return chatBytes[key]; });
const chatBytesBuffer = new Uint8Array(_chatBytesBuffer)
chatBytesBuffer.set(_nonce, 112)
const signature = nacl.sign.detached(chatBytesBuffer, keyPair.privateKey)
const signedBytes = utils.appendBuffer(chatBytesBuffer, signature)
return signedBytes
} else {
const chatBytesBuffer = new Uint8Array(chatBytes)
chatBytesBuffer.set(_nonce, 112)
const signature = nacl.sign.detached(chatBytesBuffer, keyPair.privateKey)
const signedBytes = utils.appendBuffer(chatBytesBuffer, signature)
return signedBytes
}
}
export default signChat

View File

@@ -0,0 +1,90 @@
"use strict";
import TransactionBase from "../TransactionBase.js"
export default class CreateGroupTransaction extends TransactionBase {
constructor() {
super()
this.type = 22
this.fee = 0.001
// this.tests.push(
// () => {
// if (!(this._registrantAddress instanceof Uint8Array && this._registrantAddress.length == 25)) {
// return "Invalid Registrant " + Base58.encode(this._registrantAddress)
// }
// return true
// }
// )
}
render(html) {
return html`
You are requesting to creating the group below:
<div style="background:#eee; padding:8px; margin:8px 0; border-radius:2px;">
<div>Group Name: <span>${this._rGroupName}</span></div>
<br>
<div>Group Description: <span>${this._rGroupDesc}</span></div>
<br>
<div>Group Type: <span>${this.myGroupType === 1 ? "Public" : "Private"}</span></div>
</div>
On pressing confirm, the group request will be sent!
`
}
// set registrantAddress(registrantAddress) {
// this._registrantAddress = registrantAddress instanceof Uint8Array ? registrantAddress : this.constructor.Base58.decode(registrantAddress);
// }
set rGroupName(rGroupName) {
this._rGroupName = rGroupName;
this._rGroupNameBytes = this.constructor.utils.stringtoUTF8Array(this._rGroupName.toLocaleLowerCase())
this._rGroupNameLength = this.constructor.utils.int32ToBytes(this._rGroupNameBytes.length)
}
set rGroupDesc(rGroupDesc) {
this._rGroupDesc = rGroupDesc;
this._rGroupDescBytes = this.constructor.utils.stringtoUTF8Array(this._rGroupDesc.toLocaleLowerCase())
this._rGroupDescLength = this.constructor.utils.int32ToBytes(this._rGroupDescBytes.length)
}
set rGroupType(rGroupType) {
this.myGroupType = rGroupType;
this._rGroupType = new Uint8Array(1)
this._rGroupType[0] = rGroupType;
}
set rGroupApprovalThreshold(rGroupApprovalThreshold) {
this._rGroupApprovalThreshold = new Uint8Array(1)
this._rGroupApprovalThreshold[0] = rGroupApprovalThreshold;
}
set rGroupMinimumBlockDelay(rGroupMinimumBlockDelay) {
this._rGroupMinimumBlockDelay = rGroupMinimumBlockDelay;
this._rGroupMinimumBlockDelayBytes = this.constructor.utils.int32ToBytes(this._rGroupMinimumBlockDelay)
}
set rGroupMaximumBlockDelay(rGroupMaximumBlockDelay) {
this._rGroupMaximumBlockDelay = rGroupMaximumBlockDelay;
this._rGroupMaximumBlockDelayBytes = this.constructor.utils.int32ToBytes(this._rGroupMaximumBlockDelay)
}
get params() {
const params = super.params;
params.push(
// this._registrantAddress,
this._rGroupNameLength,
this._rGroupNameBytes,
this._rGroupDescLength,
this._rGroupDescBytes,
this._rGroupType,
this._rGroupApprovalThreshold,
this._rGroupMinimumBlockDelayBytes,
this._rGroupMaximumBlockDelayBytes,
this._feeBytes
)
return params;
}
}

View File

@@ -0,0 +1,51 @@
"use strict";
import TransactionBase from "../TransactionBase.js"
export default class JoinGroupTransaction extends TransactionBase {
constructor() {
super()
this.type = 31
this.fee = 0.001 // THOUGHTS: Fee should be easily set and dynamic in future... (0.001)
this.tests.push(
() => {
if (!(this._registrantAddress instanceof Uint8Array && this._registrantAddress.length == 25)) {
return "Invalid Registrant " + Base58.encode(this._registrantAddress)
}
return true
}
)
}
render(html) {
return html`
You are requesting to join the group below:
<div style="background:#eee; padding:8px; margin:8px 0; border-radius:2px;">
<span>${this._rGroupName}</span>
</div>
On pressing confirm, the group request will be sent!
`
}
set registrantAddress(registrantAddress) {// Always Base58 encoded. Accepts Uint8Array or Base58 string.
this._registrantAddress = registrantAddress instanceof Uint8Array ? registrantAddress : this.constructor.Base58.decode(registrantAddress);
}
set rGroupId(rGroupId) {
this._rGroupId = rGroupId;
this._rGroupIdBytes = this.constructor.utils.int32ToBytes(this._rGroupId)
}
set rGroupName(rGroupName) {
this._rGroupName = rGroupName;
}
get params() {
const params = super.params;
params.push(
this._rGroupIdBytes,
this._feeBytes
)
return params;
}
}

View File

@@ -0,0 +1,51 @@
"use strict";
import TransactionBase from "../TransactionBase.js"
export default class LeaveGroupTransaction extends TransactionBase {
constructor() {
super()
this.type = 32
this.fee = 0.001 // THOUGHTS: Fee should be easily set and dynamic in future... (0.001)
this.tests.push(
() => {
if (!(this._registrantAddress instanceof Uint8Array && this._registrantAddress.length == 25)) {
return "Invalid Registrant " + Base58.encode(this._registrantAddress)
}
return true
}
)
}
render(html) {
return html`
You are requesting to leave the group below:
<div style="background:#eee; padding:8px; margin:8px 0; border-radius:2px;">
<span>${this._rGroupName}</span>
</div>
On pressing confirm, the group request will be sent!
`
}
set registrantAddress(registrantAddress) {// Always Base58 encoded. Accepts Uint8Array or Base58 string.
this._registrantAddress = registrantAddress instanceof Uint8Array ? registrantAddress : this.constructor.Base58.decode(registrantAddress);
}
set rGroupId(rGroupId) {
this._rGroupId = rGroupId;
this._rGroupIdBytes = this.constructor.utils.int32ToBytes(this._rGroupId)
}
set rGroupName(rGroupName) {
this._rGroupName = rGroupName;
}
get params() {
const params = super.params;
params.push(
this._rGroupIdBytes,
this._feeBytes
)
return params;
}
}

View File

@@ -0,0 +1,55 @@
"use strict";
import TransactionBase from "../TransactionBase.js"
import { QORT_DECIMALS } from "../../constants.js"
export default class RegisterNameTransaction extends TransactionBase {
constructor() {
super()
this.type = 3
this.fee = 0.001
// this.tests.push(
// () => {
// if (!(this._registrantAddress instanceof Uint8Array && this._registrantAddress.length == 25)) {
// return "Invalid registrant " + Base58.encode(this._registrantAddress)
// }
// return true
// }
// )
}
render(html) {
return html`
You are registering the name below:
<div style="background:#eee; padding:8px; margin:8px 0; border-radius:2px;">
<span>${this.nameText}</span>
</div>
On pressing confirm, the name will be registered!
`
}
set name(name) {
this.nameText = name;
this._nameBytes = this.constructor.utils.stringtoUTF8Array(name)
this._nameLength = this.constructor.utils.int32ToBytes(this._nameBytes.length)
}
set value(value) {
this.valueText = value.length === 0 ? "Registered Name on the Qortal Chain" : value;
this._valueBytes = this.constructor.utils.stringtoUTF8Array(this.valueText)
this._valueLength = this.constructor.utils.int32ToBytes(this._valueBytes.length)
}
get params() {
const params = super.params;
params.push(
this._nameLength,
this._nameBytes,
this._valueLength,
this._valueBytes,
this._feeBytes
)
return params;
}
}

View File

@@ -0,0 +1,39 @@
"use strict";
/*
TO DO
*/
(function(){
function generateSignatureRegisterNameTransaction(keyPair, lastReference, owner, name, value, fee, timestamp) => {
const data = generateRegisterNameTransactionBase(keyPair.publicKey, lastReference, owner, name, value, fee, timestamp);
return nacl.sign.detached(data, keyPair.privateKey);
}
function generateRegisterNameTransaction(keyPair, lastReference, owner, name, value, fee, timestamp, signature) => {
return appendBuffer( generateRegisterNameTransactionBase(keyPair.publicKey, lastReference, owner, name, value, fee, timestamp),
signature );
}
function generateRegisterNameTransactionBase(publicKey, lastReference, owner, name, value, fee, timestamp) => {
const txType = TYPES.REGISTER_NAME_TRANSACTION;
const typeBytes = int32ToBytes(txType);
const timestampBytes = int64ToBytes(timestamp);
const feeBytes = int64ToBytes(fee * 100000000);
const nameSizeBytes = int32ToBytes(name.length);
const valueSizeBytes = int32ToBytes(value.length);
let data = new Uint8Array();
data = appendBuffer(data, typeBytes);
data = appendBuffer(data, timestampBytes);
data = appendBuffer(data, lastReference);
data = appendBuffer(data, publicKey);
data = appendBuffer(data, owner);
data = appendBuffer(data, nameSizeBytes);
data = appendBuffer(data, name);
data = appendBuffer(data, valueSizeBytes);
data = appendBuffer(data, value);
data = appendBuffer(data, feeBytes);
return data;
}
}())

View File

@@ -0,0 +1,54 @@
"use strict";
import TransactionBase from "../TransactionBase.js"
import publicKeyToAddress from '../../wallet/publicKeyToAddress.js'
import { Base58 } from "../../deps/deps.js";
export default class RemoveRewardShareTransaction extends TransactionBase {
constructor() {
super()
this.type = 38
}
render(html) {
return html`
You are removing a reward share transaction associated with account:
<div style="background:#eee; padding:8px; margin:8px 0; border-radius:2px;">
<span>${this.constructor.Base58.encode(this._recipient)}</span>
</div>
On pressing confirm, the rewardshare will be removed and the minting key will become invalid.
`
}
set rewardShareKeyPairPublicKey(rewardShareKeyPairPublicKey) {
this._rewardShareKeyPairPublicKey = Base58.decode(rewardShareKeyPairPublicKey)
}
set recipient(recipient) {
const _address = publicKeyToAddress(this._keyPair.publicKey)
this._recipient = recipient instanceof Uint8Array ? recipient : this.constructor.Base58.decode(recipient)
this.fee = _address === recipient ? 0 : 0.001
}
set percentageShare(share) {
this._percentageShare = share * 100
this._percentageShareBytes = this.constructor.utils.int64ToBytes(this._percentageShare)
}
get params() {
const params = super.params
params.push(
this._recipient,
this._rewardShareKeyPairPublicKey,
this._percentageShareBytes,
this._feeBytes
)
return params;
}
}

View File

@@ -0,0 +1,64 @@
import publicKeyToAddress from '../../wallet/publicKeyToAddress.js'
"use strict";
import TransactionBase from "../TransactionBase.js"
import nacl from '../../deps/nacl-fast.js'
import ed2curve from '../../deps/ed2curve.js'
import { Sha256 } from 'asmcrypto.js'
export default class RewardShareTransaction extends TransactionBase {
constructor() {
super()
this.type = 38
}
render(html) {
return html`
Would you like to create a reward share transaction, sharing <strong>${this._percentageShare / 1e8}%</strong> of your minting rewards with <strong>${this.constructor.Base58.encode(this._recipient)}</strong>?
If yes, you will need to save the key below in order to mint. It can be supplied to any node in order to allow it to mint on your behalf.
<div style="background:#eee; padding:8px; margin:8px 0; border-radius:2px;">
<span>${this._base58RewardShareSeed}</span>
</div>
On pressing confirm, the rewardshare will be created, but you will still need to supply the above key to a node in order to mint with the account.
`
}
set recipientPublicKey(recipientPublicKey) {
this._base58RecipientPublicKey = recipientPublicKey instanceof Uint8Array ? this.constructor.Base58.encode(recipientPublicKey) : recipientPublicKey
this._recipientPublicKey = this.constructor.Base58.decode(this._base58RecipientPublicKey)
this.recipient = publicKeyToAddress(this._recipientPublicKey)
this.fee = (recipientPublicKey === this.constructor.Base58.encode(this._keyPair.publicKey) ? 0 : 0.001)
// Reward share keys
const convertedPrivateKey = ed2curve.convertSecretKey(this._keyPair.privateKey)
const convertedPublicKey = ed2curve.convertPublicKey(this._recipientPublicKey)
const sharedSecret = new Uint8Array(32);
nacl.lowlevel.crypto_scalarmult(sharedSecret, convertedPrivateKey, convertedPublicKey);
this._rewardShareSeed = new Sha256().process(sharedSecret).finish().result
this._base58RewardShareSeed = this.constructor.Base58.encode(this._rewardShareSeed)
this._rewardShareKeyPair = nacl.sign.keyPair.fromSeed(this._rewardShareSeed)
}
set recipient(recipient) { // Always Base58 encoded. Accepts Uint8Array or Base58 string.
this._recipient = recipient instanceof Uint8Array ? recipient : this.constructor.Base58.decode(recipient)
}
set percentageShare(share) {
this._percentageShare = share * 100
this._percentageShareBytes = this.constructor.utils.int64ToBytes(this._percentageShare)
}
get params() {
const params = super.params
params.push(
this._recipient,
this._rewardShareKeyPair.publicKey,
this._percentageShareBytes,
this._feeBytes
)
return params;
}
}

View File

@@ -0,0 +1,79 @@
/**
* CrossChain - TradeBot Create Request (Sell Action)
*
* These are special types of transactions (JSON ENCODED)
*/
export default class TradeBotCreateRequest {
constructor() {
// ...
}
createTransaction(txnReq) {
this.creatorPublicKey(txnReq.creatorPublicKey);
this.qortAmount(txnReq.qortAmount);
this.fundingQortAmount(txnReq.fundingQortAmount);
this.foreignBlockchain(txnReq.foreignBlockchain);
this.foreignAmount(txnReq.foreignAmount);
this.tradeTimeout(txnReq.tradeTimeout);
this.receivingAddress(txnReq.receivingAddress);
return this.txnRequest();
}
creatorPublicKey(creatorPublicKey) {
this._creatorPublicKey = creatorPublicKey;
}
qortAmount(qortAmount) {
this._qortAmount = qortAmount;
}
fundingQortAmount(fundingQortAmount) {
this._fundingQortAmount = fundingQortAmount;
}
foreignBlockchain(foreignBlockchain) {
this._foreignBlockchain = foreignBlockchain;
}
foreignAmount(foreignAmount) {
this._foreignAmount = foreignAmount;
}
tradeTimeout(tradeTimeout) {
this._tradeTimeout = tradeTimeout;
}
receivingAddress(receivingAddress) {
this._receivingAddress = receivingAddress;
}
txnRequest() {
return {
creatorPublicKey: this._creatorPublicKey,
qortAmount: this._qortAmount,
fundingQortAmount: this._fundingQortAmount,
foreignBlockchain: this._foreignBlockchain,
foreignAmount: this._foreignAmount,
tradeTimeout: this._tradeTimeout,
receivingAddress: this._receivingAddress
}
}
}

View File

@@ -0,0 +1,45 @@
/**
* CrossChain - TradeBot Respond Request (Buy Action)
*
* These are special types of transactions (JSON ENCODED)
*/
export default class TradeBotRespondRequest {
constructor() {
// ...
}
createTransaction(txnReq) {
this.atAddress(txnReq.atAddress)
this.foreignKey(txnReq.foreignKey)
this.receivingAddress(txnReq.receivingAddress)
return this.txnRequest()
}
atAddress(atAddress) {
this._atAddress = atAddress
}
foreignKey(foreignKey) {
this._foreignKey = foreignKey
}
receivingAddress(receivingAddress) {
this._receivingAddress = receivingAddress
}
txnRequest() {
return {
atAddress: this._atAddress,
foreignKey: this._foreignKey,
receivingAddress: this._receivingAddress
}
}
}

View File

@@ -0,0 +1,38 @@
import Base58 from '../../../deps/Base58.js'
import nacl from '../../../deps/nacl-fast.js'
import utils from '../../../deps/utils.js'
const signTradeBotTransaction = (unsignedTxn, keyPair) => {
if (!unsignedTxn) {
throw new Error('Unsigned Transaction Bytes not defined')
}
if (!keyPair) {
throw new Error('keyPair not defined')
}
const txnBuffer = Base58.decode(unsignedTxn)
if (keyPair.privateKey.length === undefined) {
const _privateKey = Object.keys(keyPair.privateKey).map(function (key) { return keyPair.privateKey[key]; });
const privateKey = new Uint8Array(_privateKey)
const signature = nacl.sign.detached(txnBuffer, privateKey)
const signedBytes = utils.appendBuffer(txnBuffer, signature)
return signedBytes
} else {
const signature = nacl.sign.detached(txnBuffer, keyPair.privateKey)
const signedBytes = utils.appendBuffer(txnBuffer, signature)
return signedBytes
}
}
export default signTradeBotTransaction

View File

@@ -0,0 +1,39 @@
/**
* CrossChain - DELETE TradeOffer
*
* These are special types of transactions (JSON ENCODED)
*/
export default class DeleteTradeOffer {
constructor() {
// ...
}
createTransaction(txnReq) {
this.creatorPublicKey(txnReq.creatorPublicKey)
this.atAddress(txnReq.atAddress)
return this.txnRequest()
}
creatorPublicKey(creatorPublicKey) {
this._creatorPublicKey = creatorPublicKey
}
atAddress(atAddress) {
this._atAddress = atAddress
}
txnRequest() {
return {
creatorPublicKey: this._creatorPublicKey,
atAddress: this._atAddress
}
}
}

View File

@@ -0,0 +1,24 @@
import { request } from '../../../fetch-request.js'
import { deleteTradeOffer, signTradeBotTxn } from '../../../tradeRequest.js';
import { processTransaction } from '../../../createTransaction.js'
export const cancelAllOffers = async (requestObject) => {
const keyPair = requestObject.keyPair;
const publicKey = requestObject.base58PublicKey;
const address = requestObject.address;
const getMyOpenOffers = async () => {
const res = await request('/crosschain/tradeoffers');
const myOpenTradeOrders = await res.filter(order => order.mode === "OFFERING" && order.qortalCreator === address);
return myOpenTradeOrders;
}
const myOpenOffers = await getMyOpenOffers();
let response = true;
myOpenOffers.forEach( async (openOffer) => {
let unsignedTxn = await deleteTradeOffer({ creatorPublicKey: publicKey, atAddress: openOffer.qortalAtAddress });
let signedTxnBytes = await signTradeBotTxn(unsignedTxn, keyPair);
await processTransaction(signedTxnBytes);
});
return response
}

View File

@@ -0,0 +1,25 @@
import PaymentTransaction from './PaymentTransaction.js'
import MessageTransaction from './MessageTransaction.js'
import RegisterNameTransaction from './names/RegisterNameTransaction.js'
import ChatTransaction from './chat/ChatTransaction.js'
import GroupChatTransaction from './chat/GroupChatTransaction.js';
import RewardShareTransaction from './reward-share/RewardShareTransaction.js'
import RemoveRewardShareTransaction from './reward-share/RemoveRewardShareTransaction.js'
import CreateGroupTransaction from './groups/CreateGroupTransaction.js';
import JoinGroupTransaction from './groups/JoinGroupTransaction.js'
import LeaveGroupTransaction from './groups/LeaveGroupTransaction.js'
import PublicizeTransaction from './PublicizeTransaction.js'
export const transactionTypes = {
2: PaymentTransaction,
3: RegisterNameTransaction,
17: MessageTransaction,
18: ChatTransaction,
181: GroupChatTransaction,
19: PublicizeTransaction,
22: CreateGroupTransaction,
31: JoinGroupTransaction,
32: LeaveGroupTransaction,
38: RewardShareTransaction,
381: RemoveRewardShareTransaction
}

View File

@@ -0,0 +1,11 @@
export const randomBase58Generator = (digits) => {
digits = digits || 0
let base58 = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'.split('')
let result = ''
let char
while (result.length < digits) {
char = base58[Math.random() * 57 >> 0]
if (result.indexOf(char) === -1) result += char
}
return result
}

View File

@@ -0,0 +1,31 @@
import { store } from '../../api.js'
let subscriptions = []
// Have to wait with init because something import stateAwait before the store gets initialized
let initialized = false
const init = () => {
initialized = true
store.subscribe(() => {
const state = store.getState()
subscriptions = subscriptions.filter(fn => fn(state))
})
}
export const stateAwait = fn => {
return new Promise((resolve, reject) => {
// Check immediately...then if not true store it
if (!initialized) {
init()
}
if (fn(store.getState())) resolve()
subscriptions.push(state => {
if (fn(state)) {
resolve()
return true
}
return false
})
})
}

View File

@@ -0,0 +1,11 @@
import publicKeyToAddress from './publicKeyToAddress'
import Base58 from '../deps/Base58.js'
export const base58PublicKeyToAddress = (base58pubkey, qora = false) => {
const decodePubKey = Base58.decode(base58pubkey)
const address = publicKeyToAddress(decodePubKey, qora)
return address
}

View File

@@ -0,0 +1,37 @@
import RIPEMD160 from '../deps/ripemd160.js'
import BROKEN_RIPEMD160 from '../deps/broken-ripemd160.js'
import { Sha256 } from 'asmcrypto.js'
import utils from '../deps/utils.js'
import Base58 from '../deps/Base58.js'
import { Buffer } from 'buffer'
import { ADDRESS_VERSION } from '../constants.js'
const repeatSHA256 = (passphrase, hashes) => {
let hash = passphrase
for (let i = 0; i < hashes; i++) {
hash = new Sha256().process(hash).finish().result
}
return hash
}
const publicKeyToAddress = (publicKey, qora = false) => {
const publicKeySha256 = new Sha256().process(publicKey).finish().result
const _publicKeyHash = qora ? new BROKEN_RIPEMD160().digest(publicKeySha256) : new RIPEMD160().update(Buffer.from(publicKeySha256)).digest('hex')
const publicKeyHash = qora ? _publicKeyHash : _publicKeyHash
let address = new Uint8Array()
address = utils.appendBuffer(address, [ADDRESS_VERSION])
address = utils.appendBuffer(address, publicKeyHash)
const checkSum = repeatSHA256(address, 2)
address = utils.appendBuffer(address, checkSum.subarray(0, 4))
address = Base58.encode(address)
return address
}
export default publicKeyToAddress

View File

@@ -0,0 +1,12 @@
import Base58 from '../deps/Base58.js'
export const validateAddress = (address) => {
const decodePubKey = Base58.decode(address)
if (!(decodePubKey instanceof Uint8Array && decodePubKey.length == 25)) {
return false
}
return true
}