Skip to content

Commit

Permalink
Support/coin hedera (#8118)
Browse files Browse the repository at this point in the history
* coin modul hedera

---------

Co-authored-by: qperrot <[email protected]>
  • Loading branch information
Wozacosta and qperrot authored Nov 6, 2024
1 parent a1016cc commit 17d52ce
Show file tree
Hide file tree
Showing 61 changed files with 1,181 additions and 339 deletions.
8 changes: 8 additions & 0 deletions .changeset/ten-mangos-hide.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@ledgerhq/coin-hedera": minor
"@ledgerhq/hw-app-hedera": patch
"@actions/turbo-affected": patch
"@ledgerhq/live-common": patch
---

Creation of coin-hedera package
33 changes: 33 additions & 0 deletions libs/coin-modules/coin-hedera/.unimportedrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"entry": [
"src/account.ts",
"src/bridge/index.ts",
"src/test/cli.ts",
"src/deviceTransactionConfig.ts",
"src/errors.ts",
"src/hw-getAddress.ts",
"src/specs.ts",
"src/transaction.ts"
],
"ignorePatterns": [
"**/node_modules/**",
"**/*.fixture.ts",
"**/*.mock.ts",
"**/*.test.{js,jsx,ts,tsx}"
],
"ignoreUnresolved": [],
"ignoreUnimported": [
"src/index.ts",
"src/test/bot-specs.ts",
"src/test/bridgeDatasetTest.ts",
"src/test/cli.ts",
"src/test/index.ts",
"src/test/speculos-deviceActions.ts"
],
"ignoreUnused": [
"@ledgerhq/devices",
"expect",
"lodash",
"rxjs"
]
}
9 changes: 9 additions & 0 deletions libs/coin-modules/coin-hedera/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/** @type {import('ts-jest/dist/types').JestConfigWithTsJest} */
module.exports = {
collectCoverageFrom: ["src/**/*.ts"],
coverageDirectory: "coverage",
preset: "ts-jest",
testEnvironment: "node",
testPathIgnorePatterns: ["lib/", "lib-es/", ".integration.test.ts"],
modulePathIgnorePatterns: ["__tests__/fixtures"],
};
112 changes: 112 additions & 0 deletions libs/coin-modules/coin-hedera/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
{
"name": "@ledgerhq/coin-hedera",
"version": "1.0.0",
"description": "Ledger Hedera Coin integration",
"keywords": [
"Ledger",
"LedgerWallet",
"hbar",
"Hedera",
"Hardware Wallet"
],
"repository": {
"type": "git",
"url": "https://github.com/LedgerHQ/ledger-live.git"
},
"bugs": {
"url": "https://github.com/LedgerHQ/ledger-live/issues"
},
"homepage": "https://github.com/LedgerHQ/ledger-live/tree/develop/libs/coin-modules/coin-hedera",
"publishConfig": {
"access": "public"
},
"typesVersions": {
"*": {
"lib/*": [
"lib/*"
],
"lib-es/*": [
"lib-es/*"
],
"specs": [
"lib/test/bot-specs"
],
"*": [
"lib/*"
]
}
},
"exports": {
"./lib/*": "./lib/*.js",
"./lib-es/*": "./lib-es/*.js",
"./api": {
"require": "./lib/api/index.js",
"default": "./lib-es/api/index.js"
},
"./deviceTransactionConfig": {
"require": "./lib/deviceTransactionConfig.js",
"default": "./lib-es/deviceTransactionConfig.js"
},
"./signer": {
"require": "./lib/signer/index.js",
"default": "./lib-es/signer/index.js"
},
"./specs": {
"require": "./lib/test/bot-specs.js",
"default": "./lib-es/test/bot-specs.js"
},
"./transaction": {
"require": "./lib/transaction.js",
"default": "./lib-es/transaction.js"
},
"./types": {
"require": "./lib/types/index.js",
"default": "./lib-es/types/index.js"
},
"./*": {
"require": "./lib/*.js",
"default": "./lib-es/*.js"
},
".": {
"require": "./lib/index.js",
"default": "./lib-es/index.js"
},
"./package.json": "./package.json"
},
"license": "Apache-2.0",
"dependencies": {
"@ledgerhq/coin-framework": "workspace:^",
"@ledgerhq/cryptoassets": "workspace:^",
"@ledgerhq/devices": "workspace:^",
"@ledgerhq/errors": "workspace:^",
"@ledgerhq/live-env": "workspace:^",
"@ledgerhq/live-network": "workspace:^",
"@ledgerhq/types-live": "workspace:^",
"@ledgerhq/live-countervalues": "workspace:^",
"@hashgraph/sdk": "2.14.2",
"expect": "^27.4.6",
"invariant": "^2.2.2",
"lodash": "^4.17.21",
"bignumber.js": "^9.1.2",
"rxjs": "^7.8.1"
},
"devDependencies": {
"@types/invariant": "^2.2.2",
"@types/jest": "^29.5.10",
"@types/lodash": "^4.14.191",
"jest": "^29.7.0",
"ts-jest": "^29.1.1"
},
"scripts": {
"clean": "rimraf lib lib-es",
"build": "tsc && tsc -m ES6 --outDir lib-es",
"coverage": "jest --coverage --testPathIgnorePatterns='/bridge.integration.test.ts|node_modules|lib-es|lib/' --passWithNoTests && mv coverage/coverage-final.json coverage/coverage-hedera.json",
"prewatch": "pnpm build",
"watch": "tsc --watch",
"doc": "documentation readme src/** --section=API --pe ts --re ts --re d.ts",
"lint": "eslint ./src --no-error-on-unmatched-pattern --ext .ts,.tsx --cache",
"lint:fix": "pnpm lint --fix",
"test": "jest",
"unimported": "unimported"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@ import network from "@ledgerhq/live-network/network";
import { Operation, OperationType } from "@ledgerhq/types-live";
import BigNumber from "bignumber.js";
import { getEnv } from "@ledgerhq/live-env";
import { encodeOperationId } from "../../../operation";
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
import { getAccountBalance } from "./network";
import { base64ToUrlSafeBase64 } from "../utils";
import { base64ToUrlSafeBase64 } from "../bridge/utils";

const getMirrorApiUrl = (): string => getEnv("API_HEDERA_MIRROR");

const fetch = path => {
const fetch = (path: string) => {
return network({
method: "GET",
url: `${getMirrorApiUrl()}${path}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ import {
HbarUnit,
} from "@hashgraph/sdk";
import { Account } from "@ledgerhq/types-live";
import { Transaction } from "../types";
import { HederaAddAccountError } from "../errors";
import { Transaction } from "../types";

export function broadcastTransaction(transaction: HederaTransaction): Promise<TransactionResponse> {
return transaction.execute(getClient());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Transaction as HederaSDKTransaction } from "@hashgraph/sdk";
import { AccountBridge } from "@ledgerhq/types-live";
import { broadcastTransaction } from "./api/network";
import { patchOperationWithHash } from "../../operation";
import { patchOperationWithHash } from "@ledgerhq/coin-framework/operation";
import { base64ToUrlSafeBase64 } from "./utils";
import { Transaction } from "./types";
import { Transaction } from "../types";
import { broadcastTransaction } from "../api/network";

export const broadcast: AccountBridge<Transaction>["broadcast"] = async ({ signedOperation }) => {
const { signature, operation } = signedOperation;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Account, Operation } from "@ledgerhq/types-live";
import { encodeOperationId } from "../../operation";
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
import { getEstimatedFees } from "./utils";
import { Transaction } from "./types";
import { Transaction } from "../types";

export const buildOptimisticOperation = async ({
account,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import BigNumber from "bignumber.js";
import { AccountBridge } from "@ledgerhq/types-live";
import { Transaction } from "./types";
import { Transaction } from "../types";

/**
* Creates an empty transaction.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import BigNumber from "bignumber.js";
import type { AccountBridge } from "@ledgerhq/types-live";
import { getMainAccount } from "../../account/index";
import type { Transaction } from "./types";
import { getMainAccount } from "@ledgerhq/coin-framework/account/index";
import type { Transaction } from "../types";
import { getEstimatedFees } from "./utils";

export const estimateMaxSpendable: AccountBridge<Transaction>["estimateMaxSpendable"] = async ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import { AccountId } from "@hashgraph/sdk";
import type { AccountBridge } from "@ledgerhq/types-live";
import { calculateAmount, getEstimatedFees } from "./utils";
import type { Transaction } from "./types";
import type { Transaction } from "../types";

export const getTransactionStatus: AccountBridge<Transaction>["getTransactionStatus"] = async (
account,
Expand Down
60 changes: 60 additions & 0 deletions libs/coin-modules/coin-hedera/src/bridge/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import { makeScanAccounts, makeSync } from "@ledgerhq/coin-framework/bridge/jsHelpers";
import resolver from "../signer/index";
import getAddressWrapper from "@ledgerhq/coin-framework/bridge/getAddressWrapper";
import { SignerContext } from "@ledgerhq/coin-framework/signer";
import type { Account, AccountBridge, CurrencyBridge } from "@ledgerhq/types-live";
import { defaultUpdateTransaction } from "@ledgerhq/coin-framework/bridge/jsHelpers";
import type { Transaction, TransactionStatus, HederaSigner } from "../types";
import { getTransactionStatus } from "./getTransactionStatus";
import { estimateMaxSpendable } from "./estimateMaxSpendable";
import { prepareTransaction } from "./prepareTransaction";
import { createTransaction } from "./createTransaction";
import { getAccountShape, buildIterateResult } from "./synchronisation";
import { buildSignOperation } from "./signOperation";
import { broadcast } from "./broadcast";
import { receive } from "./receive";

function buildCurrencyBridge(signerContext: SignerContext<HederaSigner>): CurrencyBridge {
const getAddress = resolver(signerContext);

const scanAccounts = makeScanAccounts({
getAccountShape,
buildIterateResult,
getAddressFn: getAddressWrapper(getAddress),
});

return {
preload: () => Promise.resolve({}),
hydrate: () => {},
scanAccounts,
};
}

const sync = makeSync({ getAccountShape });

function buildAccountBridge(
signerContext: SignerContext<HederaSigner>,
): AccountBridge<Transaction, Account, TransactionStatus> {
const getAddress = resolver(signerContext);

const signOperation = buildSignOperation(signerContext);

return {
estimateMaxSpendable,
createTransaction,
updateTransaction: defaultUpdateTransaction,
getTransactionStatus,
prepareTransaction,
sync,
receive: receive(getAddressWrapper(getAddress)),
signOperation,
broadcast,
};
}

export function createBridges(signerContext: SignerContext<HederaSigner>) {
return {
currencyBridge: buildCurrencyBridge(signerContext),
accountBridge: buildAccountBridge(signerContext),
};
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import BigNumber from "bignumber.js";
import type { Account } from "@ledgerhq/types-live";
import { estimateMaxSpendable } from "../estimateMaxSpendable";
import { getEstimatedFees } from "../utils";
import { createBridges } from ".";
import { getEstimatedFees } from "./utils";

// Balance is 1 Hbar
const account: Account = {
Expand Down Expand Up @@ -43,14 +43,17 @@ const account: Account = {
};

describe("js-estimateMaxSpendable", () => {
let bridge: ReturnType<typeof createBridges>;
let estimatedFees = new BigNumber("150200").multipliedBy(2); // 0.001502 ℏ (as of 2023-03-14)

beforeAll(async () => {
const signer = jest.fn();
bridge = createBridges(signer);
estimatedFees = await getEstimatedFees(account);
});

test("estimateMaxSpendable", async () => {
const result = await estimateMaxSpendable({
const result = await bridge.accountBridge.estimateMaxSpendable({
account,
});
const data = account.balance.minus(estimatedFees);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import BigNumber from "bignumber.js";
import type { Account } from "@ledgerhq/types-live";
import { defaultUpdateTransaction as updateTransaction } from "@ledgerhq/coin-framework/bridge/jsHelpers";
import type { Transaction } from "../../../families/hedera/types";
import { createTransaction } from "../createTransaction";
import { prepareTransaction } from "../prepareTransaction";
import type { Transaction } from "../types";
import { createBridges } from ".";

const account: Account = {
type: "Account",
Expand Down Expand Up @@ -51,9 +50,15 @@ const transaction: Transaction = {
};

describe("js-transaction", () => {
let bridge: ReturnType<typeof createBridges>;

beforeAll(() => {
const signer = jest.fn();
bridge = createBridges(signer);
});
test("createTransaction", () => {
const data = transaction;
const result = createTransaction(account);
const result = bridge.accountBridge.createTransaction(account);

expect(result).toEqual(data);
});
Expand All @@ -72,7 +77,7 @@ describe("js-transaction", () => {

test("prepareTransaction", async () => {
const data = transaction;
const result = await prepareTransaction(account, transaction);
const result = await bridge.accountBridge.prepareTransaction(account, transaction);

expect(result).toEqual(data);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { AccountBridge } from "@ledgerhq/types-live";
import type { Transaction } from "./types";
import type { Transaction } from "../types";
import { calculateAmount } from "./utils";

/**
Expand Down
Loading

0 comments on commit 17d52ce

Please sign in to comment.