Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Csv import fixes #1584

Merged
merged 22 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
4362d56
bump: v0.9.1 version bump
jbair06 Feb 19, 2025
1c79c9b
fix: export allows naming of file, default name provided
jbair06 Feb 19, 2025
eeaf044
chore: playwright version bump
jbair06 Feb 19, 2025
e2e62e8
fix: resolving flagged issues
jbair06 Feb 20, 2025
500db29
fix: resolving more flagged issues
jbair06 Feb 20, 2025
01783d2
test: add tests for failed saveFileNamed
jbair06 Feb 20, 2025
5538416
fix: cvs importing and transfer item computed description
jbair06 Feb 21, 2025
091dcef
chore: move reusable code out of CreateTransactionGroup
jbair06 Feb 21, 2025
d797362
bump: v0.9.2
jbair06 Feb 21, 2025
dcbf64c
fix: transaction description saves from csv
jbair06 Feb 25, 2025
02597d1
fix: transfer amounts can contain commas
jbair06 Feb 25, 2025
c052562
chore: use text-secondary color for symbol
jbair06 Feb 25, 2025
45ab333
bump: v0.9.1 version bump
jbair06 Feb 19, 2025
bdabf89
fix: export allows naming of file, default name provided
jbair06 Feb 19, 2025
7ba44a0
fix: resolving more flagged issues
jbair06 Feb 20, 2025
f958fcd
fix: cvs importing and transfer item computed description
jbair06 Feb 21, 2025
ba49181
chore: move reusable code out of CreateTransactionGroup
jbair06 Feb 21, 2025
d692b48
bump: v0.9.2
jbair06 Feb 21, 2025
2c72728
fix: transaction description saves from csv
jbair06 Feb 25, 2025
a5a538e
fix: transfer amounts can contain commas
jbair06 Feb 25, 2025
a47d2b3
chore: use text-secondary color for symbol
jbair06 Feb 25, 2025
b171202
Merge branch 'csv-import-fixes' of https://github.com/hashgraph/heder…
jbair06 Feb 26, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion back-end/apps/api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@back-end/api",
"version": "0.9.1",
"version": "0.9.2",
"description": "",
"author": "",
"main": "index.js",
Expand Down
2 changes: 1 addition & 1 deletion back-end/apps/chain/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@back-end/chain",
"version": "0.9.1",
"version": "0.9.2",
"description": "",
"author": "",
"main": "index.js",
Expand Down
2 changes: 1 addition & 1 deletion back-end/apps/notifications/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@back-end/notifications",
"version": "0.9.1",
"version": "0.9.2",
"description": "",
"author": "",
"main": "index.js",
Expand Down
2 changes: 1 addition & 1 deletion back-end/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "back-end",
"version": "0.9.1",
"version": "0.9.2",
"description": "",
"author": "",
"private": true,
Expand Down
2 changes: 1 addition & 1 deletion front-end/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hedera-transaction-tool",
"version": "0.9.1",
"version": "0.9.2",
"description": "Transaction tool application",
"author": {
"name": "Hedera",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue';

import { Hbar, KeyList, PublicKey, TransferTransaction, Transaction } from '@hashgraph/sdk';
import { Hbar, KeyList, PublicKey, TransferTransaction, Transaction, HbarUnit } from '@hashgraph/sdk';

import useUserStore from '@renderer/stores/storeUser';
import useTransactionGroupStore from '@renderer/stores/storeTransactionGroup';
Expand All @@ -15,6 +15,7 @@ import { deleteGroup } from '@renderer/services/transactionGroupsService';

import {
assertUserLoggedIn,
formatHbarTransfers,
getErrorMessage,
getPropagationButtonLabel,
isLoggedInOrganization,
Expand Down Expand Up @@ -208,7 +209,7 @@ async function handleOnFileChanged(e: Event) {
const target = e.target as HTMLInputElement;
reader.readAsText(target.files![0]);
reader.onload = () => {
const result = (reader.result as string).replace(/['"]+/g, '');
const result = reader.result as string;
const rows = result.split(/\r?\n|\r|\n/g);
let senderAccount = '';
let feePayer = '';
Expand All @@ -218,27 +219,34 @@ async function handleOnFileChanged(e: Event) {
let memo = '';
let validStart: Date | null = null;
for (const row of rows) {
const title = row.split(',')[0].toLowerCase();
const rowInfo = row.match(/(?:"(?:\\"|[^"])*"|[^,]+)(?=,|$)/g)
?.map(s => s.trim()
.replace(/^"|"$/g, '')
.replace(/\\"/g, '"')) || [];
const title = rowInfo[0]?.toLowerCase();
switch (title) {
case 'transaction description':
groupDescription.value = rowInfo[1];
break;
case 'sender account':
senderAccount = row.split(',')[1];
senderAccount = rowInfo[1];
break;
case 'fee payer account':
feePayer = row.split(',')[1];
feePayer = rowInfo[1];
break;
case 'sending time':
sendingTime = row.split(',')[1];
sendingTime = rowInfo[1];
break;
case 'node ids':
break;
case 'transaction fee':
transactionFee = row.split(',')[1];
transactionFee = rowInfo[1];
break;
case 'transaction valid duration':
txValidDuration = row.split(',')[1];
txValidDuration = rowInfo[1];
break;
case 'memo':
memo = row.split(',')[1];
memo = rowInfo[1];
break;
case 'accountid':
case 'account id':
Expand All @@ -249,7 +257,7 @@ async function handleOnFileChanged(e: Event) {
} else {
// Create the new validStart value, or add 1 millisecond to the existing one for subsequent transactions
if (!validStart) {
const startDate = row.split(',')[2];
const startDate = rowInfo[2];
validStart = new Date(`${startDate} ${sendingTime}`);
if (validStart < new Date()) {
validStart = new Date();
Expand All @@ -261,16 +269,23 @@ async function handleOnFileChanged(e: Event) {
.setTransactionValidDuration(txValidDuration ? Number.parseInt(txValidDuration) : 180)
.setMaxTransactionFee(
transactionFee
? new Hbar(transactionFee)
: Hbar.fromString(maxTransactionFee.value.toString()),
? new Hbar(transactionFee, HbarUnit.Tinybar)
: maxTransactionFee.value
);

transaction.setTransactionId(
createTransactionId(feePayer ? feePayer : senderAccount, validStart),
);
transaction.addHbarTransfer(row.split(',')[0], row.split(',')[1]);
transaction.addHbarTransfer(senderAccount, Number.parseFloat(row.split(',')[1]) * -1);
transaction.setTransactionMemo(memo);
const transferAmount = rowInfo[1].replace(/,/g, '');
transaction.addHbarTransfer(rowInfo[0], new Hbar(transferAmount, HbarUnit.Tinybar));
transaction.addHbarTransfer(senderAccount, new Hbar(-transferAmount, HbarUnit.Tinybar));
// If memo is not provided for the row, use the memo from the header portion
// otherwise check if the memo is not 'n/a' and set it
if (rowInfo.length < 4 || !(rowInfo[3]?.trim())) {
transaction.setTransactionMemo(memo);
} else if (!/^(n\/a)$/i.test(rowInfo[3])) {
transaction.setTransactionMemo(rowInfo[3]);
}

const transactionBytes = transaction.toBytes();
const keys = new Array<string>();
Expand Down Expand Up @@ -315,12 +330,8 @@ function makeTransfer(index: number) {
transactionGroup.groupItems[index].transactionBytes,
) as TransferTransaction
).hbarTransfersList;
const transfer =
transfers.length == 2
? `${transfers[0].accountId} --> ${transfers[1].amount} --> ${transfers[1].accountId}`
: 'Multiple Transfers';

return transfer;
return formatHbarTransfers(transfers);
}

/* Hooks */
Expand Down Expand Up @@ -480,17 +491,14 @@ onBeforeRouteLeave(async to => {
<div
class="align-self-center text-truncate col text-center mx-5"
:data-testid="'span-transaction-timestamp-' + index"
>
{{
groupItem.type == 'Transfer Transaction'
? makeTransfer(index)
: groupItem.description != ''
? groupItem.description
: Transaction.fromBytes(groupItem.transactionBytes).transactionMemo
? Transaction.fromBytes(groupItem.transactionBytes).transactionMemo
: createTransactionId(groupItem.payerAccountId, groupItem.validStart)
}}
</div>
v-html="groupItem.type == 'Transfer Transaction'
? makeTransfer(index)
: groupItem.description != ''
? groupItem.description
: Transaction.fromBytes(groupItem.transactionBytes).transactionMemo
? Transaction.fromBytes(groupItem.transactionBytes).transactionMemo
: createTransactionId(groupItem.payerAccountId, groupItem.validStart)"
></div>
<div class="d-flex col justify-content-end">
<AppButton
type="button"
Expand Down
12 changes: 11 additions & 1 deletion front-end/src/renderer/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { AccountInfo } from '@main/shared/interfaces';
import type { HederaAccount } from '@prisma/client';

import { AccountId, Client } from '@hashgraph/sdk';
import { AccountId, Client, Hbar, HbarUnit } from '@hashgraph/sdk';

import useUserStore from '@renderer/stores/storeUser';
import useNetworkStore from '@renderer/stores/storeNetwork';
Expand All @@ -15,6 +15,7 @@ import { isAccountId } from './validator';
export * from './dom';
export * from './sdk';
export * from './transactions';
export * from './transferTransactions';
export * from './validator';
export * from './axios';
export * from './ipc';
Expand Down Expand Up @@ -186,6 +187,15 @@ export const getAccountIdWithChecksum = (accountId: string): string => {
}
};

export function stringifyHbarWithFont(hbar: Hbar, fontClass: string): string {
const tinybars = Math.abs(hbar.toTinybars());
const isHbar = tinybars >= Hbar.fromTinybars(1_000_000).toTinybars();
const symbol = isHbar ? HbarUnit.Hbar._symbol : HbarUnit.Tinybar._symbol;
const amountString = isHbar ? hbar.to(HbarUnit.Hbar).toString() : hbar.to(HbarUnit.Tinybar).toString();

return `${amountString} <span class="${fontClass}">${symbol}</span>`;
}

export const splitMultipleAccounts = (input: string, client: Client): string[] => {
input = input.trim();

Expand Down
33 changes: 33 additions & 0 deletions front-end/src/renderer/utils/transferTransactions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { stringifyHbarWithFont } from './index';

export function formatHbarTransfers(transfers): string {
if (transfers.length === 0) {
return 'No transfers';
}

if (transfers.length === 1) {
const amount = transfers[0].amount;
if (amount.isNegative()) {
return 'Missing receiver';
} else {
return 'Missing sender';
}
}

if (transfers.length === 2) {
// the JS SDK sorts the order of the transfers by account ID. We don't want this. We want the sender to be on the
// left and the receiver to be on the right. So we need to check if the amount is negative or positive and then
// arrange the transfers accordingly
let sender = transfers[0];
let receiver = transfers[1];
if (receiver.amount.isNegative()) {
sender = transfers[1];
receiver = transfers[0];
}
return `${sender.accountId} --> ${stringifyHbarWithFont(
receiver.amount, "text-bold text-secondary"
)} --> ${receiver.accountId}`;
}

return 'Multiple transfers';
}
Loading