Skip to content

Commit

Permalink
Merge pull request #39 from ava-labs/dev
Browse files Browse the repository at this point in the history
v0.12.0
  • Loading branch information
kanatliemre authored Jan 6, 2022
2 parents 936317a + 2ecdc5a commit fb54d70
Show file tree
Hide file tree
Showing 49 changed files with 2,544 additions and 1,397 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
with:
cache: yarn
node-version: ${{ env.node_version }}
- run: yarn --frozen-lockfile
- run: yarn --frozen-lockfile --network-timeout 1000000
- run: yarn test --ci --coverage --maxWorkers=2
Lint:
runs-on: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -111,5 +111,5 @@ public/
# End of https://www.gitignore.io/api/node.idea/*

.markdownlint.json

TODO.md

18 changes: 9 additions & 9 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"docs:watch": "typedoc --watch src/index.ts"
},
"peerDependencies": {
"avalanche": "3.8.*"
"avalanche": "3.10.*"
},
"lint-staged": {
"**/*": "prettier --write --ignore-unknown"
Expand All @@ -40,6 +40,7 @@
"@babel/core": "^7.14.0",
"@babel/preset-env": "^7.14.1",
"@babel/preset-typescript": "^7.13.0",
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-typescript": "^8.2.1",
"@types/big.js": "^6.0.2",
Expand All @@ -50,6 +51,7 @@
"@typescript-eslint/eslint-plugin": "^4.22.1",
"@typescript-eslint/parser": "^4.22.1",
"@zerollup/ts-transform-paths": "^1.7.18",
"avalanche": "3.10.1",
"babel-jest": "^26.6.3",
"babel-plugin-module-resolver": "^4.1.0",
"eslint": "^7.25.0",
Expand All @@ -69,12 +71,12 @@
"typescript": "^4.2.4"
},
"dependencies": {
"@ethereumjs/common": "2.4.0",
"@ethereumjs/tx": "3.3.0",
"@ethereumjs/common": "2.6.0",
"@ethereumjs/tx": "3.4.0",
"@ledgerhq/hw-app-eth": "6.12.2",
"@ledgerhq/hw-transport": "^6.19.0",
"@obsidiansystems/hw-app-avalanche": "0.2.2",
"@openzeppelin/contracts": "4.3.3",
"avalanche": "3.8.1",
"@openzeppelin/contracts": "4.4.1",
"big.js": "^6.1.1",
"bip32": "^2.0.6",
"bip32-path": "^0.4.2",
Expand All @@ -83,13 +85,11 @@
"create-hash": "1.2.0",
"ethereumjs-util": "^7.0.7",
"ethers": "^5.1.4",
"moment": "^2.29.1",
"rollup-plugin-commonjs": "^10.1.0",
"sockette": "^2.0.6",
"typescript-transform-paths": "^2.2.3",
"url": "^0.11.0",
"web3": "^1.3.5",
"web3-eth-contract": "^1.3.6",
"web3": "1.6.0",
"web3-eth-contract": "1.6.0",
"xss": "^1.0.10"
}
}
2 changes: 1 addition & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import json from '@rollup/plugin-json';
import commonjs from 'rollup-plugin-commonjs';
import commonjs from '@rollup/plugin-commonjs';
import del from 'rollup-plugin-delete';
import ttypescript from 'ttypescript';
import typescript from 'rollup-plugin-typescript2';
Expand Down
25 changes: 13 additions & 12 deletions src/Keystore/keystore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,14 @@ import {
} from './types';
import { xChain } from '@/Network/network';
import { Buffer } from 'buffer/';
import MnemonicWallet from '@/Wallet/MnemonicWallet';
import { MnemonicWallet } from '@/Wallet/MnemonicWallet';
import Crypto from './Crypto';
import SingletonWallet from '@/Wallet/SingletonWallet';
import { SingletonWallet } from '@/Wallet/SingletonWallet';
import { AccessWalletMultipleInput } from './types';
// import { keyToKeypair } from '@/helpers/helper'
import * as bip39 from 'bip39';
import { bintools } from '@/common';
import { Buffer as AjsBuffer } from 'avalanche';

const cryptoHelpers = new Crypto();

Expand Down Expand Up @@ -63,7 +64,7 @@ async function readV2(data: KeyFileV2, pass: string) {

let checkHashString: string;
let checkHash: Buffer = await cryptoHelpers._pwcleaner(pass, salt);
checkHashString = bintools.cb58Encode(checkHash);
checkHashString = bintools.cb58Encode(AjsBuffer.from(checkHash));

if (checkHashString !== pass_hash) {
throw 'INVALID_PASS';
Expand All @@ -79,7 +80,7 @@ async function readV2(data: KeyFileV2, pass: string) {
let nonce: Buffer = bintools.cb58Decode(key_data.iv);

let key_decrypt: Buffer = await cryptoHelpers.decrypt(pass, key, salt, nonce);
let key_string = bintools.cb58Encode(key_decrypt);
let key_string = bintools.cb58Encode(AjsBuffer.from(key_decrypt));

keysDecrypt.push({
key: key_string,
Expand All @@ -101,7 +102,7 @@ async function readV3(data: KeyFileV3, pass: string) {

let checkHashString: string;
let checkHash: IHash = await cryptoHelpers.pwhash(pass, salt);
checkHashString = bintools.cb58Encode(checkHash.hash);
checkHashString = bintools.cb58Encode(AjsBuffer.from(checkHash.hash));

if (checkHashString !== pass_hash) {
throw 'INVALID_PASS';
Expand All @@ -117,7 +118,7 @@ async function readV3(data: KeyFileV3, pass: string) {
let nonce: Buffer = bintools.cb58Decode(key_data.iv);

let key_decrypt: Buffer = await cryptoHelpers.decrypt(pass, key, salt, nonce);
let key_string = bintools.cb58Encode(key_decrypt);
let key_string = bintools.cb58Encode(AjsBuffer.from(key_decrypt));

keysDecrypt.push({
key: key_string,
Expand All @@ -139,7 +140,7 @@ async function readV4(data: KeyFileV4, pass: string): Promise<KeyFileDecryptedV5

let checkHashString: string;
let checkHash: IHash = await cryptoHelpers.pwhash(pass, salt);
checkHashString = bintools.cb58Encode(checkHash.hash);
checkHashString = bintools.cb58Encode(AjsBuffer.from(checkHash.hash));

if (checkHashString !== pass_hash) {
throw 'INVALID_PASS';
Expand All @@ -155,7 +156,7 @@ async function readV4(data: KeyFileV4, pass: string): Promise<KeyFileDecryptedV5
let nonce: Buffer = bintools.cb58Decode(key_data.iv);

let key_decrypt: Buffer = await cryptoHelpers.decrypt(pass, key, salt, nonce);
let key_string = bintools.cb58Encode(key_decrypt);
let key_string = bintools.cb58Encode(AjsBuffer.from(key_decrypt));

keysDecrypt.push({
key: key_string,
Expand All @@ -178,7 +179,7 @@ async function readV5(data: KeyFileV5, pass: string): Promise<KeyFileDecryptedV5

let checkHashString: string;
let checkHash: IHash = await cryptoHelpers.pwhash(pass, salt);
checkHashString = bintools.cb58Encode(checkHash.hash);
checkHashString = bintools.cb58Encode(AjsBuffer.from(checkHash.hash));

if (checkHashString !== pass_hash) {
throw 'INVALID_PASS';
Expand Down Expand Up @@ -357,16 +358,16 @@ async function makeKeyfile(
let pk_crypt: PKCrypt = await cryptoHelpers.encrypt(pass, key, salt);

let key_data: KeyFileKeyV6 = {
key: bintools.cb58Encode(pk_crypt.ciphertext),
iv: bintools.cb58Encode(pk_crypt.iv),
key: bintools.cb58Encode(AjsBuffer.from(pk_crypt.ciphertext)),
iv: bintools.cb58Encode(AjsBuffer.from(pk_crypt.iv)),
type: type,
};
keys.push(key_data);
}

let file_data: KeyFileV6 = {
version: KEYSTORE_VERSION,
salt: bintools.cb58Encode(salt),
salt: bintools.cb58Encode(AjsBuffer.from(salt)),
activeIndex,
keys: keys,
};
Expand Down
2 changes: 0 additions & 2 deletions src/Network/constants.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { NetworkConfig } from './types';
// import { AVMConstants } from 'avalanche/dist/apis/avm';
// import Avalanche, { AvalancheCore } from 'avalanche';
import { Defaults } from 'avalanche/dist/utils';
import { getRpcC, getRpcP, getRpcX } from './helpers/rpcFromConfig';

Expand Down
17 changes: 17 additions & 0 deletions src/Network/helpers/idFromAlias.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ChainIdType } from '@/types';
import { cChain, pChain, xChain } from '@/Network/network';

/**
* Given a chain alias, returns the chain id.
* @param alias `X`, `P` or `C`
*/
export function chainIdFromAlias(alias: ChainIdType) {
if (alias === 'X') {
return xChain.getBlockchainID();
} else if (alias === 'P') {
return pChain.getBlockchainID();
} else if (alias === 'C') {
return cChain.getBlockchainID();
}
throw new Error('Unknown chain alias.');
}
3 changes: 3 additions & 0 deletions src/Network/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './aliasFromNetworkID';
export * from './idFromAlias';
export * from './rpcFromConfig';
1 change: 1 addition & 0 deletions src/Network/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,4 @@ export function getActiveNetworkConfig() {
export { WebsocketProvider, getEvmChainID, getConfigFromUrl };

export { NetworkConfig } from './types';
export * from './helpers';
148 changes: 148 additions & 0 deletions src/UniversalTx/UniversalNode.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { BN } from 'avalanche';
import { ChainIdType } from '@/types';
import {
UniversalTx,
UniversalTxActionExport,
UniversalTxActionImport,
UniversalTxExport,
UniversalTxImport,
} from './types';

export abstract class UniversalNodeAbstract {
parents: UniversalNodeAbstract[];
child: UniversalNodeAbstract | null; // can only have 1 child
balance: BN;
chain: ChainIdType;
feeExport: BN;
feeImport: BN;

protected constructor(balance: BN, chain: ChainIdType, feeExport: BN, feeImport: BN) {
this.parents = [];
this.child = null;
this.balance = balance;
this.chain = chain;
this.feeExport = feeExport;
this.feeImport = feeImport;
}

// Sum of the node's balance + all balance of parents minus the transfer fees
reduceTotalBalanceFromParents(): BN {
// If there are no balance return balance of self
if (this.parents.length === 0) {
return this.balance;
}

let parentBals = this.parents.map((node) => {
// Subtract transfer fees from parent balance
// import + export
let parentBalance = node.reduceTotalBalanceFromParents();
parentBalance = parentBalance.sub(this.feeImport).sub(node.feeExport);
let zero = new BN(0);
return BN.max(parentBalance, zero);
});

let tot = parentBals.reduce((prev, current) => {
return prev.add(current);
}, new BN(0));

return tot.add(this.balance);
}

/**
* Returns the export action type from this node to its child
* @param to
*/
abstract getExportMethod(to: ChainIdType): UniversalTxActionExport;

/**
* Returns the import action type from this node to its child
* @param from Which chain are we importing from
*/
abstract getImportMethod(from: ChainIdType): UniversalTxActionImport;

buildExportTx(destChain: ChainIdType, amount: BN): UniversalTxExport {
return {
action: this.getExportMethod(destChain),
amount: amount,
fee: this.feeExport,
};
}

buildImportTx(sourceChain: ChainIdType): UniversalTxImport {
return {
action: this.getImportMethod(sourceChain),
fee: this.feeImport,
};
}

/***
* Assumes there is enough balance on node tree
* Returns empty array even if transaction not possible!
* What steps to take to have the target balance on this node.
* @param target Amount of nAVAX needed on this node.
*/
getStepsForTargetBalance(target: BN): UniversalTx[] {
// If the node has enough balance no transaction needed
// If target is negative or zero no transaction needed
if (this.balance.gte(target) || target.lte(new BN(0))) {
return [];
}

// If not enough balance and no parents
// return all the balance
if (this.balance.lt(target) && this.parents.length === 0) {
return [];
}

// If not enough balance on this node, try to collect it from parents
// Amount needed to collect from parents
let remaining = target.sub(this.balance);

let transactions = [];
for (let i = 0; i < this.parents.length; i++) {
let p = this.parents[i];

if (remaining.lte(new BN(0))) break;

// Parent's balance
let pBal = p.reduceTotalBalanceFromParents();
const exportFee = p.feeExport;
const importFee = this.feeImport;
const feeImportExport = exportFee.add(importFee);
// Maximum balance we can import from parent
let pBalMax = pBal.sub(feeImportExport);
// The parent needs to have this balance to satisfy the needed amount

// Try to export the remaining amount, if the parent balance is lower than that export the maximum amount
// Import amount is the usable amount imported
const importAmt = BN.min(pBalMax, remaining); // The amount that will cross to the target chain
// Exported amount should include the import fees
const exportAmt = importAmt.add(importFee);

if (exportAmt.lte(new BN(0))) continue;

let pTx = p.buildExportTx(this.chain, exportAmt);
let importTx = this.buildImportTx(p.chain);

transactions.push(pTx);
transactions.push(importTx);

remaining = remaining.sub(importAmt);
}

// If we still have remaining balance, we can not complete this transfer
if (remaining.gt(new BN(0))) {
throw new Error('Insufficient AVAX balances.');
}

return transactions;
}

addParent(node: UniversalNodeAbstract) {
this.parents.push(node);
}

setChild(node: UniversalNodeAbstract) {
this.child = node;
}
}
Loading

0 comments on commit fb54d70

Please sign in to comment.