Skip to content

Commit

Permalink
Merge pull request #121 from ava-labs/dev
Browse files Browse the repository at this point in the history
feat: Ledger v2
  • Loading branch information
kanatliemre authored Jan 20, 2023
2 parents 896f8ba + fa462e7 commit 1789665
Show file tree
Hide file tree
Showing 19 changed files with 1,366 additions and 1,209 deletions.
13 changes: 7 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "0.18.5",
"version": "0.19.0",
"license": "BSD-3",
"main": "dist/index.js",
"typings": "dist/index.d.ts",
Expand Down Expand Up @@ -69,10 +69,11 @@
"typescript": "4.6.3"
},
"dependencies": {
"@avalabs/hw-app-avalanche": "0.6.6",
"@ethereumjs/common": "2.6.0",
"@ethereumjs/tx": "3.4.0",
"@ledgerhq/hw-app-eth": "6.12.2",
"@ledgerhq/hw-transport": "6.27.4",
"@ledgerhq/hw-app-eth": "6.29.6",
"@ledgerhq/hw-transport": "6.27.5",
"@metamask/eth-sig-util": "4.0.0",
"@obsidiansystems/hw-app-avalanche": "0.2.2",
"@openzeppelin/contracts": "4.7.3",
Expand All @@ -92,11 +93,11 @@
"sockette": "2.0.6",
"typescript-transform-paths": "2.2.3",
"url": "0.11.0",
"web3": "1.7.3",
"web3-eth-contract": "1.7.1",
"web3": "1.8.1",
"web3-eth-contract": "1.8.1",
"xss": "1.0.11"
},
"peerDependencies": {
"avalanche": "3.15.2"
"avalanche": ">= 3.15.2"
}
}
1 change: 1 addition & 0 deletions src/Csv/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './constants';
export * from './createCsvContent';
export * from './parseStakingTxs';
export * from './parseNormalTxs';
export * from './parseTxUtxos';
140 changes: 140 additions & 0 deletions src/Csv/parseTxUtxos.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { findDestinationChain, findSourceChain, OrteliusAvalancheTx, OrteliusTransactionType } from '@/Explorer';
import { ChainIdType } from '@/common';
import { activeNetwork, idToChainAlias } from '@/Network';
import { isOutputOwner } from '@/Explorer/ortelius/utxoUtils';
import { createCSVContent } from '@/Csv/createCsvContent';
import { bnToBig } from '@/utils';
import { BN } from 'avalanche';

interface ParsedTxUtxos {
txID: string;
timeStamp: Date;
unixTime: string;
txType: OrteliusTransactionType;
chain: ChainIdType;
isInput: boolean;
isOwner: boolean;
amount: string;
owners: string[];
locktime: number;
threshold: number;
assetID: string;
}

function isExportTx(tx: OrteliusAvalancheTx) {
return tx.type === 'export' || tx.type === 'pvm_export' || tx.type === 'atomic_export_tx';
}

function isImport(tx: OrteliusAvalancheTx) {
return tx.type === 'import' || tx.type === 'pvm_import' || tx.type === 'atomic_import_tx';
}

/**
* Given an array of Ortelius transaction data return input and outputs as a single unified array
* @param txs
* @param ownedAddresses
*/
export function parseTxUtxos(txs: OrteliusAvalancheTx[], ownedAddresses: string[]) {
const result: ParsedTxUtxos[] = [];
txs.forEach((tx) => {
const date = new Date(tx.timestamp);

const chainId = isExportTx(tx) ? findSourceChain(tx) : findDestinationChain(tx);
const chainAlias = idToChainAlias(chainId);

tx.inputs?.forEach((txIn) => {
const isAVAX = txIn.output.assetID === activeNetwork.avaxID;
const decimals = isAVAX ? 9 : 0;
result.push({
txID: tx.id,
timeStamp: date,
unixTime: date.getTime().toString(),
txType: tx.type,
chain: chainAlias,
isInput: true,
isOwner: isOutputOwner(ownedAddresses, txIn.output),
amount: bnToBig(new BN(txIn.output.amount), decimals).toString(),
owners: txIn.output.addresses || txIn.output.caddresses || [],
locktime: txIn.output.locktime,
threshold: txIn.output.threshold,
assetID: isAVAX ? 'AVAX' : txIn.output.assetID,
});
});

tx.outputs?.forEach((txOut) => {
const isAVAX = txOut.assetID === activeNetwork.avaxID;
const decimals = isAVAX ? 9 : 0;

result.push({
txID: tx.id,
unixTime: date.getTime().toString(),
timeStamp: date,
txType: tx.type,
chain: chainAlias,
isInput: false,
isOwner: isOutputOwner(ownedAddresses, txOut),
amount: bnToBig(new BN(txOut.amount), decimals).toString(),
owners: txOut.addresses || txOut.caddresses || [],
locktime: txOut.locktime,
threshold: txOut.threshold,
assetID: isAVAX ? 'AVAX' : txOut.assetID,
});
});
});

return result;
}

/**
* Create CSV file contents from the given Ortelius transactions.
* @param txs Array of Ortelius Transactions
* @param ownedAddresses Addresses owned by the wallet.
*/
export function createCsvFileOrtelius(txs: OrteliusAvalancheTx[], ownedAddresses: string[]) {
type CsvRow = [string, string, string, string, string, string, string, string, string, string, string, string];
const parsed = parseTxUtxos(txs, ownedAddresses);

const headers: CsvRow = [
'Tx ID',
'Timestamp',
'UNIX Timestamp',
'Tx Type',
'Chain',
'input/output',
'Owned',
'Amount',
'Asset ID',
'Owners',
'Locktime',
'Threshold',
];
const rows: CsvRow[] = [];

const unsupportedtypes: OrteliusTransactionType[] = [
'add_validator',
'add_delegator',
'add_subnet_validator',
'operation',
'create_asset',
'create_subnet',
'create_chain',
];
parsed.forEach((tx) => {
if (unsupportedtypes.includes(tx.txType)) return;
rows.push([
tx.txID,
tx.timeStamp.toISOString(),
tx.unixTime,
tx.txType,
tx.chain,
tx.isInput ? 'input' : 'output',
tx.isOwner ? 'TRUE' : 'FALSE',
`"${tx.amount}"`,
tx.assetID,
tx.owners.join('-'),
tx.locktime.toString(),
tx.threshold.toString(),
]);
});
return createCSVContent([headers, ...rows]);
}
5 changes: 5 additions & 0 deletions src/Explorer/ortelius/utxoUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ export function isArraysOverlap(arr1: any[], arr2: any[]): boolean {
* @param output The UTXO
*/
export function isOutputOwner(ownerAddrs: string[], output: OrteliusUTXO): boolean {
// Remove prefix from owner addresses
ownerAddrs = ownerAddrs.map((addr) => {
const split = addr.split('-');
return split[1] || split[0];
});
let outAddrs = output.addresses;
if (!outAddrs) return false;

Expand Down
34 changes: 34 additions & 0 deletions src/History/getHistoryForOwnedAddresses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export async function getHistoryForOwnedAddresses(
]);

let txsXPC = filterDuplicateOrtelius(txsX.concat(txsP, txsC));

let txsEVM = await getHistoryEVM(evmAddress);

let addrs = [...xAddresses, cAddress];
Expand Down Expand Up @@ -81,3 +82,36 @@ export async function getHistoryForOwnedAddresses(
}
return txsSorted;
}

/**
* Returns sorted history data from Ortelius for X, P, and C chains.
* @param xAddresses A list of owned X chain addresses
* @param pAddresses A list of owned P chain addresses
* @param cAddress Bech32 C chain address
* @param limit Number of transactions to fetch, undefined or 0 for all history
*/
export async function getHistoryForOwnedAddressesRaw(
xAddresses: string[],
pAddresses: string[],
cAddress: string,
limit = 0
) {
let [txsX, txsP, txsC] = await Promise.all([
getHistoryX(xAddresses, limit),
getHistoryP(pAddresses, limit),
getHistoryC(cAddress, xAddresses, limit),
]);

let txsXPC = filterDuplicateOrtelius(txsX.concat(txsP, txsC));
let txsSorted = txsXPC.sort((x, y) => {
const dateX = new Date(x.timestamp);
const dateY = new Date(y.timestamp);
return dateX.getTime() < dateY.getTime() ? 1 : -1;
});

// If there is a limit only return that much
if (limit > 0) {
return txsSorted.slice(0, limit);
}
return txsSorted;
}
Loading

0 comments on commit 1789665

Please sign in to comment.