Skip to content

Commit

Permalink
Merge pull request #24 from luxtagofficial/develop
Browse files Browse the repository at this point in the history
Feature/Hardware wallet support
  • Loading branch information
aizaiz authored Nov 26, 2018
2 parents 6f4a085 + fdb2318 commit e987f76
Show file tree
Hide file tree
Showing 17 changed files with 4,017 additions and 5,169 deletions.
19 changes: 11 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,32 +48,35 @@
"dependencies": {
"@types/crypto-js": "^3.1.43",
"@types/lodash": "^4.14.113",
"commitizen": "^2.9.6",
"commitizen": "3.0.4",
"crypto-js": "^3.1.9-1",
"js-sha3": "^0.7.0",
"js-sha3": "0.8.0",
"lodash": "^4.17.10",
"nem-sdk": "^1.6.4",
"nem2-sdk": "^0.10.1",
"rxjs": "^6.2.2"
},
"devDependencies": {
"@types/jest": "^22.2.2",
"@types/sinon": "^5.0.1",
"@types/jest": "^23.3.9",
"@types/sinon": "5.0.7",
"codecov": "^3.0.4",
"commitlint": "^6.2.0",
"commitlint": "7.2.1",
"cz-conventional-changelog": "^2.1.0",
"ghooks": "^2.0.4",
"jest": "^23.4.1",
"npm-run-all": "^4.1.2",
"npm-run-all": "4.1.5",
"rimraf": "^2.6.2",
"semantic-release": "^15.8.1",
"sinon": "^5.0.10",
"travis-deploy-once": "^5.0.0",
"sinon": "7.1.1",
"travis-deploy-once": "5.0.9",
"ts-jest": "^23.0.1",
"tslint": "^5.11.0",
"typescript": "^2.8.3",
"validate-commit-msg": "^2.14.0"
},
"resolutions": {
"@octokit/request": "^2.1.2"
},
"files": [
"dist"
],
Expand Down
6 changes: 2 additions & 4 deletions src/infrastructure/ApostilleHttp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { AccountHttp, Address, AggregateTransaction, Listener, PublicAccount, Qu
import { filter, mergeMap } from 'rxjs/operators';
import { Errors } from '../types/Errors';

class ApostilleHttp {
export class ApostilleHttp {

private transactionHttp: TransactionHttp;
private accountHttp: AccountHttp;
Expand Down Expand Up @@ -122,7 +122,7 @@ class ApostilleHttp {
if (transaction.transactionInfo instanceof TransactionInfo) {
return transaction.transactionInfo;
} else {
throw new Error(Errors[Errors.COULD_NOT_FOUND_TRANSACTION_INFO]);
throw new Error(Errors[Errors.TRANSACTION_INFO_NOT_FOUND]);
}
} catch (error) {
throw new Error(error);
Expand Down Expand Up @@ -227,5 +227,3 @@ class ApostilleHttp {
}

}

export { ApostilleHttp };
17 changes: 9 additions & 8 deletions src/model/apostille/Apostille.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@ import { SHA256 } from '../../hash/sha256';
import { ApostillePublicAccount } from './ApostillePublicAccount';

const nem = nemSDK.default;
// TODO: add tx hash of creation
// TODO: a getter function for getting all the owners of the apostille
const fixPrivateKey = (privateKey) => {
return ('0000000000000000000000000000000000000000000000000000000000000000' + privateKey.replace(/^00/, ''))
.slice(-64);
};

/**
* @description the private apostille class
* @class Apostille
*/
class Apostille {
export class Apostille {
/**
* @description init apostille
* @static
Expand All @@ -29,9 +32,9 @@ class Apostille {
// sign the hashed seed to get the private key
if (networkType === NetworkType.MAIN_NET || networkType === NetworkType.TEST_NET) {
const keyPair = nem.crypto.keyPair.create(generatorAccount.privateKey);
privateKey = nem.utils.helpers.fixPrivateKey(keyPair.sign(hashSeed).toString());
privateKey = fixPrivateKey(keyPair.sign(hashSeed).toString());
} else {
privateKey = nem.utils.helpers.fixPrivateKey(generatorAccount.signData(hashSeed));
privateKey = fixPrivateKey(generatorAccount.signData(hashSeed));
}
// create the HD acccount (appostille)
const hdAccount = Account.createFromPrivateKey(privateKey, networkType);
Expand All @@ -44,7 +47,7 @@ class Apostille {
* @param {Account} generatorAccount - the account used to sign the hash to generate the HD account private key
* @memberof Apostille
*/
private constructor(
public constructor(
public readonly HDAccount: Account,
) {}

Expand Down Expand Up @@ -81,5 +84,3 @@ class Apostille {
}

}

export { Apostille };
177 changes: 69 additions & 108 deletions src/model/apostille/ApostillePublicAccount.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { drop } from 'lodash';
import { Account, AggregateTransaction, Deadline, LockFundsTransaction, ModifyMultisigAccountTransaction, Mosaic, MultisigCosignatoryModification, MultisigCosignatoryModificationType, PlainMessage, PublicAccount, SignedTransaction, TransferTransaction, UInt64, XEM } from 'nem2-sdk';
import { Account, AggregateTransaction, Deadline, LockFundsTransaction, ModifyMultisigAccountTransaction, Mosaic, MultisigCosignatoryModification, MultisigCosignatoryModificationType, PlainMessage, PublicAccount, SignedTransaction, Transaction, TransferTransaction, UInt64, XEM } from 'nem2-sdk';
import { HashFunction } from '../../hash/HashFunction';
import { Errors } from '../../types/Errors';

Expand Down Expand Up @@ -34,48 +34,6 @@ export class ApostillePublicAccount {
return creationTransaction;
}

/**
* @description - returning a signed transfer transaction for the apostille account
* @param {string} rawData - the raw data to send in the payload
* @param {(Mosaic[] | Mosaic[])} [mosaics=[]] - array of mosiacs to attache
* @param {Account} initiatorAccount - the initiator of the transaction
* @param {HashFunction} [hashFunction] - if provided will hash the raw data and add a magical byte to the hash
* @returns {SignedTransaction}
* @memberof ApostilleAccount
*/
public updateAndSign(
rawData: string,
mosaics: Mosaic[] | Mosaic[] = [],
initiatorAccount: Account,
hashFunction?: HashFunction,
): SignedTransaction {
if (initiatorAccount.address.networkType !== this.publicAccount.address.networkType) {
throw new Error(Errors[Errors.NETWORK_TYPE_MISMATCHED]);
}

let data: string = rawData;
// first we create the creation transaction as a transfer transaction
if (hashFunction) {
// for digital files it's a good idea to hash the content of the file
// but can be used for other types of information for real life assets
const hash = hashFunction.signedHashing(
rawData,
initiatorAccount.privateKey,
this.publicAccount.address.networkType,
);
data = hash;
}

const creationTransaction = this.update(
data,
mosaics,
);

const signedTransaction = initiatorAccount.sign(creationTransaction);

return signedTransaction;
}

/**
* @description - modify ownership of the apostille account by modifying the multisisg contratc
* @param {PublicAccount[]} newOwners - array of new owners
Expand Down Expand Up @@ -118,39 +76,6 @@ export class ApostillePublicAccount {
return modifyMultisigAccountTransaction;
}

/**
* @description - modify ownership of the apostille account by modifying the multisisg contract
* @param {PublicAccount[]} newOwners - array of new owners
* @param {PublicAccount[]} OwnersToRemove - array of owners to remove
* @param {number} quorum - relative quorum (refer to own function above and/or http://bit.ly/2Jnff1r )
* @param {number} minRemoval - relative number of minimum owners necessary to agree to remove 1/n owners
* @param {Account[]} signers - array of accounts that will sign the transaction
* @param {boolean} isCompleteCosignatories - whether the transaction is an aggregate complete or bonded
* @returns {SignedTransaction}
* @memberof ApostillePublicAccount
*/
public transferAndSign(
newOwners: PublicAccount[],
OwnersToRemove: PublicAccount[],
quorum: number,
minRemoval: number,
signers: Account[],
isCompleteCosignatories: boolean,
): SignedTransaction {
const transferTransaction = this.transfer(
newOwners,
OwnersToRemove,
quorum,
minRemoval,
);

if (isCompleteCosignatories) {
return this._signTransferTransactionAgregateComplete(transferTransaction, signers);
} else {
return this._signTransferTransactionAggregateBonded(transferTransaction, signers);
}
}

/**
* @description returning lockFundTransactions that can be signed later on
* @param {SignedTransaction} signedAggregateBondedTransaction
Expand All @@ -169,50 +94,62 @@ export class ApostillePublicAccount {
}

/**
* @description - returning signed lockFundsTransaction for announcing aggregate bonded
* @param {SignedTransaction} signedAggregateBondedTransaction
* @param {Account} signer
* @returns {SignedTransaction}
* @description sign normal transaction (can sign update(if normal transaction) and lockFundsTransaction)
* @param {TransferTransaction} transferTransaction
* @param {Account} initiatorAccount
* @param {HashFunction} [hashFunction] - only hash transfer transaction message
* @returns
* @memberof ApostillePublicAccount
*/
public lockFundsTransactionAndSign(
signedAggregateBondedTransaction: SignedTransaction,
signer: Account,
): SignedTransaction {
// the lock need the signed aggregate transaction
const lockFundsTransaction = this.lockFundsTransaction(signedAggregateBondedTransaction);
// we sign the lock
const signedLock = signer.sign(lockFundsTransaction);

return signedLock;
}
public sign(
transaction: TransferTransaction | Transaction,
initiatorAccount: Account,
hashFunction?: HashFunction) {
if (initiatorAccount.address.networkType !== this.publicAccount.address.networkType) {
throw new Error(Errors[Errors.NETWORK_TYPE_MISMATCHED]);
}

private _signAggregate(aggregateTransaction: AggregateTransaction, signers: Account[]): SignedTransaction {
// fetch the first signer
const mainSigner = signers[0];
let tx = transaction;

// fetch the signer from index 1 till n
const cosignatories = drop(signers);
// first we create the creation transaction as a transfer transaction
if (hashFunction && tx instanceof TransferTransaction) {
// for digital files it's a good idea to hash the content of the file
// but can be used for other types of information for real life assets

// init signitTransaction
let signedTransaction: SignedTransaction;
const rawData = tx.message.payload;

if (cosignatories.length === 0) {
// it should be a 1-n account
signedTransaction = mainSigner.sign(aggregateTransaction);
} else {
// if we have cosignatories that needs to sign
signedTransaction = mainSigner.signTransactionWithCosignatories(
aggregateTransaction,
cosignatories,
const hash = hashFunction.signedHashing(
rawData,
initiatorAccount.privateKey,
this.publicAccount.address.networkType,
);

tx = this.update(hash, tx.mosaics);
}

const signedTransaction = initiatorAccount.sign(tx);

return signedTransaction;
}

/**
* @description signed aggregate transaction (can sign update(if multisig transaction) and transfer transaction)
* @param {Transaction} transaction
* @param {Account[]} signers
* @param {boolean} isCompleteCosignatories
* @returns
* @memberof ApostillePublicAccount
*/
public signAggregate(transaction: Transaction, signers: Account[], isCompleteCosignatories: boolean) {
if (isCompleteCosignatories) {
return this._signTransferTransactionAgregateComplete(transaction, signers);
} else {
return this._signTransferTransactionAggregateBonded(transaction, signers);
}
}

private _signTransferTransactionAgregateComplete(
transaction: ModifyMultisigAccountTransaction,
transaction: Transaction,
signers: Account[],
): SignedTransaction {
const aggregateTransaction = AggregateTransaction.createComplete(
Expand All @@ -227,7 +164,7 @@ export class ApostillePublicAccount {
}

private _signTransferTransactionAggregateBonded(
transaction: ModifyMultisigAccountTransaction,
transaction: Transaction,
signers: Account[],
): SignedTransaction {
const aggregateTransaction = AggregateTransaction.createBonded(
Expand All @@ -239,4 +176,28 @@ export class ApostillePublicAccount {

return signedAggregateTransaction;
}

private _signAggregate(aggregateTransaction: AggregateTransaction, signers: Account[]): SignedTransaction {
// fetch the first signer
const mainSigner = signers[0];

// fetch the signer from index 1 till n
const cosignatories = drop(signers);

// init signitTransaction
let signedTransaction: SignedTransaction;

if (cosignatories.length === 0) {
// it should be a 1-n account
signedTransaction = mainSigner.sign(aggregateTransaction);
} else {
// if we have cosignatories that needs to sign
signedTransaction = mainSigner.signTransactionWithCosignatories(
aggregateTransaction,
cosignatories,
);
}

return signedTransaction;
}
}
Loading

0 comments on commit e987f76

Please sign in to comment.