mirror of
https://github.com/Qortal/qortal-ui.git
synced 2025-11-02 21:57:51 +00:00
Initial commit
This commit is contained in:
161
qortal-ui-crypto/api/PhraseWallet.js
Normal file
161
qortal-ui-crypto/api/PhraseWallet.js
Normal 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)
|
||||
}
|
||||
}
|
||||
9
qortal-ui-crypto/api/api.js
Normal file
9
qortal-ui-crypto/api/api.js
Normal 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'
|
||||
873
qortal-ui-crypto/api/bitcoin/AltcoinHDWallet.js
Normal file
873
qortal-ui-crypto/api/bitcoin/AltcoinHDWallet.js
Normal 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
|
||||
}
|
||||
}
|
||||
2620
qortal-ui-crypto/api/bitcoin/ecbn.js
Normal file
2620
qortal-ui-crypto/api/bitcoin/ecbn.js
Normal file
File diff suppressed because it is too large
Load Diff
1940
qortal-ui-crypto/api/bitcoin/jsbn.js
Normal file
1940
qortal-ui-crypto/api/bitcoin/jsbn.js
Normal file
File diff suppressed because it is too large
Load Diff
294
qortal-ui-crypto/api/constants.js
Normal file
294
qortal-ui-crypto/api/constants.js
Normal 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
|
||||
//};
|
||||
32
qortal-ui-crypto/api/createTransaction.js
Normal file
32
qortal-ui-crypto/api/createTransaction.js
Normal 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)
|
||||
})
|
||||
30
qortal-ui-crypto/api/createWallet.js
Normal file
30
qortal-ui-crypto/api/createWallet.js
Normal 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
|
||||
}
|
||||
23
qortal-ui-crypto/api/decryptStoredWallet.js
Normal file
23
qortal-ui-crypto/api/decryptStoredWallet.js
Normal 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
|
||||
}
|
||||
108
qortal-ui-crypto/api/deps/Base58.js
Normal file
108
qortal-ui-crypto/api/deps/Base58.js
Normal 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;
|
||||
1379
qortal-ui-crypto/api/deps/bcrypt.js
Normal file
1379
qortal-ui-crypto/api/deps/bcrypt.js
Normal file
File diff suppressed because it is too large
Load Diff
180
qortal-ui-crypto/api/deps/broken-ripemd160.js
Normal file
180
qortal-ui-crypto/api/deps/broken-ripemd160.js
Normal 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
|
||||
3
qortal-ui-crypto/api/deps/deps.js
Normal file
3
qortal-ui-crypto/api/deps/deps.js
Normal file
@@ -0,0 +1,3 @@
|
||||
export { default as Base58 } from './Base58.js'
|
||||
|
||||
export { default as utils } from './utils.js'
|
||||
264
qortal-ui-crypto/api/deps/ed2curve.js
Normal file
264
qortal-ui-crypto/api/deps/ed2curve.js
Normal 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,
|
||||
}
|
||||
|
||||
// }));
|
||||
2422
qortal-ui-crypto/api/deps/nacl-fast.js
Normal file
2422
qortal-ui-crypto/api/deps/nacl-fast.js
Normal file
File diff suppressed because it is too large
Load Diff
336
qortal-ui-crypto/api/deps/qora.js
Normal file
336
qortal-ui-crypto/api/deps/qora.js
Normal 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;
|
||||
}
|
||||
226
qortal-ui-crypto/api/deps/ripemd160.js
Normal file
226
qortal-ui-crypto/api/deps/ripemd160.js
Normal 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;
|
||||
142
qortal-ui-crypto/api/deps/sha256.js
Normal file
142
qortal-ui-crypto/api/deps/sha256.js
Normal 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;
|
||||
74
qortal-ui-crypto/api/deps/utils.js
Normal file
74
qortal-ui-crypto/api/deps/utils.js
Normal 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
|
||||
30
qortal-ui-crypto/api/fetch-request.js
Normal file
30
qortal-ui-crypto/api/fetch-request.js
Normal 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()
|
||||
}
|
||||
})
|
||||
}
|
||||
39
qortal-ui-crypto/api/kdf.js
Normal file
39
qortal-ui-crypto/api/kdf.js
Normal 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
|
||||
}
|
||||
46
qortal-ui-crypto/api/registerUsername.js
Normal file
46
qortal-ui-crypto/api/registerUsername.js
Normal 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 => {})
|
||||
})
|
||||
}
|
||||
33
qortal-ui-crypto/api/storeWallet.js
Normal file
33
qortal-ui-crypto/api/storeWallet.js
Normal 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
|
||||
}
|
||||
}
|
||||
97
qortal-ui-crypto/api/tradeRequest.js
Normal file
97
qortal-ui-crypto/api/tradeRequest.js
Normal 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)
|
||||
})
|
||||
}
|
||||
50
qortal-ui-crypto/api/transactions/AirdropTransaction.js
Normal file
50
qortal-ui-crypto/api/transactions/AirdropTransaction.js
Normal 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
|
||||
}
|
||||
}
|
||||
31
qortal-ui-crypto/api/transactions/DelegationTransaction.js
Normal file
31
qortal-ui-crypto/api/transactions/DelegationTransaction.js
Normal 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
|
||||
}
|
||||
}
|
||||
95
qortal-ui-crypto/api/transactions/MessageTransaction.js
Normal file
95
qortal-ui-crypto/api/transactions/MessageTransaction.js
Normal 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;
|
||||
//}
|
||||
96
qortal-ui-crypto/api/transactions/PaymentTransaction.js
Normal file
96
qortal-ui-crypto/api/transactions/PaymentTransaction.js
Normal 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;
|
||||
// }
|
||||
23
qortal-ui-crypto/api/transactions/PublicizeTransaction.js
Normal file
23
qortal-ui-crypto/api/transactions/PublicizeTransaction.js
Normal 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;
|
||||
}
|
||||
}
|
||||
162
qortal-ui-crypto/api/transactions/TransactionBase.js
Normal file
162
qortal-ui-crypto/api/transactions/TransactionBase.js
Normal 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
|
||||
}
|
||||
}
|
||||
42
qortal-ui-crypto/api/transactions/arbitraryV3.js
Normal file
42
qortal-ui-crypto/api/transactions/arbitraryV3.js
Normal 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;
|
||||
}
|
||||
}())
|
||||
137
qortal-ui-crypto/api/transactions/chat/ChatBase.js
Normal file
137
qortal-ui-crypto/api/transactions/chat/ChatBase.js
Normal 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
|
||||
}
|
||||
|
||||
}
|
||||
77
qortal-ui-crypto/api/transactions/chat/ChatTransaction.js
Normal file
77
qortal-ui-crypto/api/transactions/chat/ChatTransaction.js
Normal 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
27
qortal-ui-crypto/api/transactions/chat/decryptChatMessage.js
Normal file
27
qortal-ui-crypto/api/transactions/chat/decryptChatMessage.js
Normal 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
|
||||
}
|
||||
46
qortal-ui-crypto/api/transactions/chat/signChat.js
Normal file
46
qortal-ui-crypto/api/transactions/chat/signChat.js
Normal 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
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
39
qortal-ui-crypto/api/transactions/registerName_dnsthing.js
Normal file
39
qortal-ui-crypto/api/transactions/registerName_dnsthing.js
Normal 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;
|
||||
}
|
||||
}())
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
25
qortal-ui-crypto/api/transactions/transactions.js
Normal file
25
qortal-ui-crypto/api/transactions/transactions.js
Normal 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
|
||||
}
|
||||
11
qortal-ui-crypto/api/utils/randomBase58Generator.js
Normal file
11
qortal-ui-crypto/api/utils/randomBase58Generator.js
Normal 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
|
||||
}
|
||||
31
qortal-ui-crypto/api/utils/stateAwait.js
Normal file
31
qortal-ui-crypto/api/utils/stateAwait.js
Normal 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
|
||||
})
|
||||
})
|
||||
}
|
||||
11
qortal-ui-crypto/api/wallet/base58PublicKeyToAddress.js
Normal file
11
qortal-ui-crypto/api/wallet/base58PublicKeyToAddress.js
Normal 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
|
||||
}
|
||||
37
qortal-ui-crypto/api/wallet/publicKeyToAddress.js
Normal file
37
qortal-ui-crypto/api/wallet/publicKeyToAddress.js
Normal 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
|
||||
12
qortal-ui-crypto/api/wallet/validateAddress.js
Normal file
12
qortal-ui-crypto/api/wallet/validateAddress.js
Normal 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
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user