@ledgerhq/coin-hedera 1.13.0-nightly.2 → 1.13.0-nightly.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +1 -1
- package/.unimportedrc.json +1 -1
- package/CHANGELOG.md +26 -0
- package/jest.config.js +1 -1
- package/jest.integ.config.js +8 -0
- package/lib/api/index.d.ts +4 -0
- package/lib/api/index.d.ts.map +1 -0
- package/lib/api/index.js +119 -0
- package/lib/api/index.js.map +1 -0
- package/lib/bridge/broadcast.d.ts +1 -1
- package/lib/bridge/broadcast.d.ts.map +1 -1
- package/lib/bridge/broadcast.js +6 -9
- package/lib/bridge/broadcast.js.map +1 -1
- package/lib/bridge/buildOptimisticOperation.d.ts.map +1 -1
- package/lib/bridge/buildOptimisticOperation.js +14 -11
- package/lib/bridge/buildOptimisticOperation.js.map +1 -1
- package/lib/bridge/createTransaction.d.ts +1 -1
- package/lib/bridge/createTransaction.d.ts.map +1 -1
- package/lib/bridge/createTransaction.js +2 -0
- package/lib/bridge/createTransaction.js.map +1 -1
- package/lib/bridge/estimateMaxSpendable.d.ts.map +1 -1
- package/lib/bridge/estimateMaxSpendable.js +2 -2
- package/lib/bridge/estimateMaxSpendable.js.map +1 -1
- package/lib/bridge/getTransactionStatus.d.ts.map +1 -1
- package/lib/bridge/getTransactionStatus.js +11 -10
- package/lib/bridge/getTransactionStatus.js.map +1 -1
- package/lib/bridge/prepareTransaction.d.ts.map +1 -1
- package/lib/bridge/prepareTransaction.js +6 -5
- package/lib/bridge/prepareTransaction.js.map +1 -1
- package/lib/bridge/signOperation.d.ts +1 -1
- package/lib/bridge/signOperation.d.ts.map +1 -1
- package/lib/bridge/signOperation.js +53 -14
- package/lib/bridge/signOperation.js.map +1 -1
- package/lib/bridge/synchronisation.d.ts.map +1 -1
- package/lib/bridge/synchronisation.js +24 -11
- package/lib/bridge/synchronisation.js.map +1 -1
- package/lib/bridge/utils.d.ts +3 -13
- package/lib/bridge/utils.d.ts.map +1 -1
- package/lib/bridge/utils.js +10 -119
- package/lib/bridge/utils.js.map +1 -1
- package/lib/config.d.ts +8 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +9 -0
- package/lib/config.js.map +1 -0
- package/lib/constants.d.ts +11 -8
- package/lib/constants.d.ts.map +1 -1
- package/lib/constants.js +17 -13
- package/lib/constants.js.map +1 -1
- package/lib/deviceTransactionConfig.d.ts +1 -1
- package/lib/deviceTransactionConfig.d.ts.map +1 -1
- package/lib/deviceTransactionConfig.js +3 -3
- package/lib/deviceTransactionConfig.js.map +1 -1
- package/lib/logic/broadcast.d.ts +3 -0
- package/lib/logic/broadcast.d.ts.map +1 -0
- package/lib/logic/broadcast.js +11 -0
- package/lib/logic/broadcast.js.map +1 -0
- package/lib/logic/combine.d.ts +2 -0
- package/lib/logic/combine.d.ts.map +1 -0
- package/lib/logic/combine.js +19 -0
- package/lib/logic/combine.js.map +1 -0
- package/lib/logic/craftTransaction.d.ts +8 -0
- package/lib/logic/craftTransaction.d.ts.map +1 -0
- package/lib/logic/craftTransaction.js +107 -0
- package/lib/logic/craftTransaction.js.map +1 -0
- package/lib/logic/estimateFees.d.ts +5 -0
- package/lib/logic/estimateFees.d.ts.map +1 -0
- package/lib/logic/estimateFees.js +25 -0
- package/lib/logic/estimateFees.js.map +1 -0
- package/lib/logic/getAssetFromToken.d.ts +4 -0
- package/lib/logic/getAssetFromToken.d.ts.map +1 -0
- package/lib/logic/getAssetFromToken.js +14 -0
- package/lib/logic/getAssetFromToken.js.map +1 -0
- package/lib/logic/getBalance.d.ts +4 -0
- package/lib/logic/getBalance.d.ts.map +1 -0
- package/lib/logic/getBalance.js +36 -0
- package/lib/logic/getBalance.js.map +1 -0
- package/lib/logic/getTokenFromAsset.d.ts +4 -0
- package/lib/logic/getTokenFromAsset.d.ts.map +1 -0
- package/lib/logic/getTokenFromAsset.js +13 -0
- package/lib/logic/getTokenFromAsset.js.map +1 -0
- package/lib/logic/index.d.ts +10 -0
- package/lib/logic/index.d.ts.map +1 -0
- package/lib/logic/index.js +22 -0
- package/lib/logic/index.js.map +1 -0
- package/lib/logic/lastBlock.d.ts +12 -0
- package/lib/logic/lastBlock.d.ts.map +1 -0
- package/lib/logic/lastBlock.js +25 -0
- package/lib/logic/lastBlock.js.map +1 -0
- package/lib/logic/listOperations.d.ts +19 -0
- package/lib/logic/listOperations.d.ts.map +1 -0
- package/lib/logic/listOperations.js +179 -0
- package/lib/logic/listOperations.js.map +1 -0
- package/lib/logic/utils.d.ts +55 -0
- package/lib/logic/utils.d.ts.map +1 -0
- package/lib/logic/utils.js +197 -0
- package/lib/logic/utils.js.map +1 -0
- package/lib/network/api.d.ts +24 -0
- package/lib/network/api.d.ts.map +1 -0
- package/lib/network/api.js +119 -0
- package/lib/network/api.js.map +1 -0
- package/lib/network/rpc.d.ts +12 -0
- package/lib/network/rpc.d.ts.map +1 -0
- package/lib/network/rpc.js +22 -0
- package/lib/network/rpc.js.map +1 -0
- package/lib/{api → network}/utils.d.ts +1 -5
- package/lib/network/utils.d.ts.map +1 -0
- package/lib/network/utils.js +52 -0
- package/lib/network/utils.js.map +1 -0
- package/lib/test/bridgeDatasetTest.d.ts.map +1 -1
- package/lib/test/bridgeDatasetTest.js +5 -1
- package/lib/test/bridgeDatasetTest.js.map +1 -1
- package/lib/test/fixtures/account.fixture.d.ts +17 -0
- package/lib/test/fixtures/account.fixture.d.ts.map +1 -1
- package/lib/test/fixtures/account.fixture.js +18 -1
- package/lib/test/fixtures/account.fixture.js.map +1 -1
- package/lib/test/fixtures/currency.fixture.d.ts.map +1 -1
- package/lib/test/fixtures/currency.fixture.js +1 -1
- package/lib/test/fixtures/currency.fixture.js.map +1 -1
- package/lib/test/fixtures/mirror.fixture.d.ts +1 -1
- package/lib/test/fixtures/mirror.fixture.d.ts.map +1 -1
- package/lib/test/fixtures/network.fixture.d.ts +3 -0
- package/lib/test/fixtures/network.fixture.d.ts.map +1 -0
- package/lib/test/fixtures/network.fixture.js +9 -0
- package/lib/test/fixtures/network.fixture.js.map +1 -0
- package/lib/test/fixtures/transaction.fixture.d.ts.map +1 -1
- package/lib/test/fixtures/transaction.fixture.js +3 -0
- package/lib/test/fixtures/transaction.fixture.js.map +1 -1
- package/lib/transaction.d.ts +1 -1
- package/lib/transaction.d.ts.map +1 -1
- package/lib/transaction.js +35 -6
- package/lib/transaction.js.map +1 -1
- package/lib/types/alpaca.d.ts +3 -0
- package/lib/types/alpaca.d.ts.map +1 -0
- package/lib/{api/types.js → types/alpaca.js} +1 -1
- package/lib/types/alpaca.js.map +1 -0
- package/lib/types/bridge.d.ts +28 -9
- package/lib/types/bridge.d.ts.map +1 -1
- package/lib/types/index.d.ts +2 -0
- package/lib/types/index.d.ts.map +1 -1
- package/lib/types/index.js +2 -0
- package/lib/types/index.js.map +1 -1
- package/lib/{api/types.d.ts → types/mirror.d.ts} +21 -2
- package/lib/types/mirror.d.ts.map +1 -0
- package/lib/types/mirror.js +3 -0
- package/lib/types/mirror.js.map +1 -0
- package/lib-es/api/index.d.ts +4 -0
- package/lib-es/api/index.d.ts.map +1 -0
- package/lib-es/api/index.js +112 -0
- package/lib-es/api/index.js.map +1 -0
- package/lib-es/bridge/broadcast.d.ts +1 -1
- package/lib-es/bridge/broadcast.d.ts.map +1 -1
- package/lib-es/bridge/broadcast.js +4 -7
- package/lib-es/bridge/broadcast.js.map +1 -1
- package/lib-es/bridge/buildOptimisticOperation.d.ts.map +1 -1
- package/lib-es/bridge/buildOptimisticOperation.js +12 -9
- package/lib-es/bridge/buildOptimisticOperation.js.map +1 -1
- package/lib-es/bridge/createTransaction.d.ts +1 -1
- package/lib-es/bridge/createTransaction.d.ts.map +1 -1
- package/lib-es/bridge/createTransaction.js +2 -0
- package/lib-es/bridge/createTransaction.js.map +1 -1
- package/lib-es/bridge/estimateMaxSpendable.d.ts.map +1 -1
- package/lib-es/bridge/estimateMaxSpendable.js +2 -2
- package/lib-es/bridge/estimateMaxSpendable.js.map +1 -1
- package/lib-es/bridge/getTransactionStatus.d.ts.map +1 -1
- package/lib-es/bridge/getTransactionStatus.js +7 -6
- package/lib-es/bridge/getTransactionStatus.js.map +1 -1
- package/lib-es/bridge/prepareTransaction.d.ts.map +1 -1
- package/lib-es/bridge/prepareTransaction.js +4 -3
- package/lib-es/bridge/prepareTransaction.js.map +1 -1
- package/lib-es/bridge/signOperation.d.ts +1 -1
- package/lib-es/bridge/signOperation.d.ts.map +1 -1
- package/lib-es/bridge/signOperation.js +53 -14
- package/lib-es/bridge/signOperation.js.map +1 -1
- package/lib-es/bridge/synchronisation.d.ts.map +1 -1
- package/lib-es/bridge/synchronisation.js +24 -11
- package/lib-es/bridge/synchronisation.js.map +1 -1
- package/lib-es/bridge/utils.d.ts +3 -13
- package/lib-es/bridge/utils.d.ts.map +1 -1
- package/lib-es/bridge/utils.js +7 -113
- package/lib-es/bridge/utils.js.map +1 -1
- package/lib-es/config.d.ts +8 -0
- package/lib-es/config.d.ts.map +1 -0
- package/lib-es/config.js +4 -0
- package/lib-es/config.js.map +1 -0
- package/lib-es/constants.d.ts +11 -8
- package/lib-es/constants.d.ts.map +1 -1
- package/lib-es/constants.js +13 -9
- package/lib-es/constants.js.map +1 -1
- package/lib-es/deviceTransactionConfig.d.ts +1 -1
- package/lib-es/deviceTransactionConfig.d.ts.map +1 -1
- package/lib-es/deviceTransactionConfig.js +1 -1
- package/lib-es/deviceTransactionConfig.js.map +1 -1
- package/lib-es/logic/broadcast.d.ts +3 -0
- package/lib-es/logic/broadcast.d.ts.map +1 -0
- package/lib-es/logic/broadcast.js +7 -0
- package/lib-es/logic/broadcast.js.map +1 -0
- package/lib-es/logic/combine.d.ts +2 -0
- package/lib-es/logic/combine.d.ts.map +1 -0
- package/lib-es/logic/combine.js +12 -0
- package/lib-es/logic/combine.js.map +1 -0
- package/lib-es/logic/craftTransaction.d.ts +8 -0
- package/lib-es/logic/craftTransaction.d.ts.map +1 -0
- package/lib-es/logic/craftTransaction.js +100 -0
- package/lib-es/logic/craftTransaction.js.map +1 -0
- package/lib-es/logic/estimateFees.d.ts +5 -0
- package/lib-es/logic/estimateFees.d.ts.map +1 -0
- package/lib-es/logic/estimateFees.js +18 -0
- package/lib-es/logic/estimateFees.js.map +1 -0
- package/lib-es/logic/getAssetFromToken.d.ts +4 -0
- package/lib-es/logic/getAssetFromToken.d.ts.map +1 -0
- package/lib-es/logic/getAssetFromToken.js +10 -0
- package/lib-es/logic/getAssetFromToken.js.map +1 -0
- package/lib-es/logic/getBalance.d.ts +4 -0
- package/lib-es/logic/getBalance.d.ts.map +1 -0
- package/lib-es/logic/getBalance.js +32 -0
- package/lib-es/logic/getBalance.js.map +1 -0
- package/lib-es/logic/getTokenFromAsset.d.ts +4 -0
- package/lib-es/logic/getTokenFromAsset.d.ts.map +1 -0
- package/lib-es/logic/getTokenFromAsset.js +9 -0
- package/lib-es/logic/getTokenFromAsset.js.map +1 -0
- package/lib-es/logic/index.d.ts +10 -0
- package/lib-es/logic/index.d.ts.map +1 -0
- package/lib-es/logic/index.js +10 -0
- package/lib-es/logic/index.js.map +1 -0
- package/lib-es/logic/lastBlock.d.ts +12 -0
- package/lib-es/logic/lastBlock.d.ts.map +1 -0
- package/lib-es/logic/lastBlock.js +21 -0
- package/lib-es/logic/lastBlock.js.map +1 -0
- package/lib-es/logic/listOperations.d.ts +19 -0
- package/lib-es/logic/listOperations.d.ts.map +1 -0
- package/lib-es/logic/listOperations.js +172 -0
- package/lib-es/logic/listOperations.js.map +1 -0
- package/lib-es/logic/utils.d.ts +55 -0
- package/lib-es/logic/utils.d.ts.map +1 -0
- package/lib-es/logic/utils.js +174 -0
- package/lib-es/logic/utils.js.map +1 -0
- package/lib-es/network/api.d.ts +24 -0
- package/lib-es/network/api.d.ts.map +1 -0
- package/lib-es/network/api.js +113 -0
- package/lib-es/network/api.js.map +1 -0
- package/lib-es/network/rpc.d.ts +12 -0
- package/lib-es/network/rpc.d.ts.map +1 -0
- package/lib-es/network/rpc.js +19 -0
- package/lib-es/network/rpc.js.map +1 -0
- package/lib-es/{api → network}/utils.d.ts +1 -5
- package/lib-es/network/utils.d.ts.map +1 -0
- package/lib-es/network/utils.js +45 -0
- package/lib-es/network/utils.js.map +1 -0
- package/lib-es/test/bridgeDatasetTest.d.ts.map +1 -1
- package/lib-es/test/bridgeDatasetTest.js +5 -1
- package/lib-es/test/bridgeDatasetTest.js.map +1 -1
- package/lib-es/test/fixtures/account.fixture.d.ts +17 -0
- package/lib-es/test/fixtures/account.fixture.d.ts.map +1 -1
- package/lib-es/test/fixtures/account.fixture.js +17 -0
- package/lib-es/test/fixtures/account.fixture.js.map +1 -1
- package/lib-es/test/fixtures/currency.fixture.d.ts.map +1 -1
- package/lib-es/test/fixtures/currency.fixture.js +1 -1
- package/lib-es/test/fixtures/currency.fixture.js.map +1 -1
- package/lib-es/test/fixtures/mirror.fixture.d.ts +1 -1
- package/lib-es/test/fixtures/mirror.fixture.d.ts.map +1 -1
- package/lib-es/test/fixtures/network.fixture.d.ts +3 -0
- package/lib-es/test/fixtures/network.fixture.d.ts.map +1 -0
- package/lib-es/test/fixtures/network.fixture.js +5 -0
- package/lib-es/test/fixtures/network.fixture.js.map +1 -0
- package/lib-es/test/fixtures/transaction.fixture.d.ts.map +1 -1
- package/lib-es/test/fixtures/transaction.fixture.js +3 -0
- package/lib-es/test/fixtures/transaction.fixture.js.map +1 -1
- package/lib-es/transaction.d.ts +1 -1
- package/lib-es/transaction.d.ts.map +1 -1
- package/lib-es/transaction.js +35 -6
- package/lib-es/transaction.js.map +1 -1
- package/lib-es/types/alpaca.d.ts +3 -0
- package/lib-es/types/alpaca.d.ts.map +1 -0
- package/lib-es/types/alpaca.js +2 -0
- package/lib-es/types/alpaca.js.map +1 -0
- package/lib-es/types/bridge.d.ts +28 -9
- package/lib-es/types/bridge.d.ts.map +1 -1
- package/lib-es/types/index.d.ts +2 -0
- package/lib-es/types/index.d.ts.map +1 -1
- package/lib-es/types/index.js +2 -0
- package/lib-es/types/index.js.map +1 -1
- package/lib-es/{api/types.d.ts → types/mirror.d.ts} +21 -2
- package/lib-es/types/mirror.d.ts.map +1 -0
- package/lib-es/types/mirror.js +2 -0
- package/lib-es/types/mirror.js.map +1 -0
- package/package.json +8 -7
- package/src/api/index.integ.test.ts +401 -0
- package/src/api/index.test.ts +30 -0
- package/src/api/index.ts +149 -0
- package/src/bridge/broadcast.ts +5 -10
- package/src/bridge/buildOptimisticOperation.integration.test.ts +8 -8
- package/src/bridge/buildOptimisticOperation.ts +13 -10
- package/src/bridge/createTransaction.ts +3 -1
- package/src/bridge/estimateMaxSpendable.ts +6 -3
- package/src/bridge/getTransactionStatus.test.ts +11 -10
- package/src/bridge/getTransactionStatus.ts +12 -11
- package/src/bridge/js-estimateMaxSpendable.integration.test.ts +6 -3
- package/src/bridge/prepareTransaction.test.ts +9 -17
- package/src/bridge/prepareTransaction.ts +5 -4
- package/src/bridge/serialization.test.ts +6 -6
- package/src/bridge/signOperation.ts +69 -16
- package/src/bridge/synchronisation.ts +22 -14
- package/src/bridge/utils.integration.test.ts +25 -248
- package/src/bridge/utils.ts +14 -160
- package/src/config.ts +7 -0
- package/src/constants.ts +15 -9
- package/src/deviceTransactionConfig.ts +2 -2
- package/src/logic/broadcast.test.ts +58 -0
- package/src/logic/broadcast.ts +8 -0
- package/src/logic/combine.test.ts +119 -0
- package/src/logic/combine.ts +14 -0
- package/src/logic/craftTransaction.test.ts +215 -0
- package/src/logic/craftTransaction.ts +175 -0
- package/src/logic/estimateFees.test.ts +99 -0
- package/src/logic/estimateFees.ts +28 -0
- package/src/logic/getAssetFromToken.test.ts +27 -0
- package/src/logic/getAssetFromToken.ts +12 -0
- package/src/logic/getBalance.test.ts +200 -0
- package/src/logic/getBalance.ts +39 -0
- package/src/logic/getTokenFromAsset.test.ts +22 -0
- package/src/logic/getTokenFromAsset.ts +17 -0
- package/src/logic/index.ts +9 -0
- package/src/logic/lastBlock.test.ts +23 -0
- package/src/logic/lastBlock.ts +23 -0
- package/src/logic/listOperations.test.ts +388 -0
- package/src/logic/listOperations.ts +247 -0
- package/src/logic/utils.test.ts +432 -0
- package/src/logic/utils.ts +255 -0
- package/src/{api/mirror.test.ts → network/api.test.ts} +81 -35
- package/src/network/api.ts +159 -0
- package/src/network/rpc.test.ts +68 -0
- package/src/network/rpc.ts +25 -0
- package/src/network/utils.test.ts +175 -0
- package/src/network/utils.ts +58 -0
- package/src/test/bridgeDatasetTest.ts +6 -2
- package/src/test/fixtures/account.fixture.ts +18 -0
- package/src/test/fixtures/currency.fixture.ts +1 -1
- package/src/test/fixtures/mirror.fixture.ts +1 -1
- package/src/test/fixtures/network.fixture.ts +6 -0
- package/src/test/fixtures/transaction.fixture.ts +5 -2
- package/src/transaction.ts +40 -9
- package/src/types/alpaca.ts +3 -0
- package/src/types/bridge.ts +36 -10
- package/src/types/index.ts +2 -0
- package/src/{api/types.ts → types/mirror.ts} +23 -1
- package/lib/api/mirror.d.ts +0 -6
- package/lib/api/mirror.d.ts.map +0 -1
- package/lib/api/mirror.js +0 -84
- package/lib/api/mirror.js.map +0 -1
- package/lib/api/network.d.ts +0 -11
- package/lib/api/network.d.ts.map +0 -1
- package/lib/api/network.js +0 -80
- package/lib/api/network.js.map +0 -1
- package/lib/api/types.d.ts.map +0 -1
- package/lib/api/types.js.map +0 -1
- package/lib/api/utils.d.ts.map +0 -1
- package/lib/api/utils.js +0 -132
- package/lib/api/utils.js.map +0 -1
- package/lib/logic.d.ts +0 -11
- package/lib/logic.d.ts.map +0 -1
- package/lib/logic.js +0 -37
- package/lib/logic.js.map +0 -1
- package/lib-es/api/mirror.d.ts +0 -6
- package/lib-es/api/mirror.d.ts.map +0 -1
- package/lib-es/api/mirror.js +0 -74
- package/lib-es/api/mirror.js.map +0 -1
- package/lib-es/api/network.d.ts +0 -11
- package/lib-es/api/network.d.ts.map +0 -1
- package/lib-es/api/network.js +0 -71
- package/lib-es/api/network.js.map +0 -1
- package/lib-es/api/types.d.ts.map +0 -1
- package/lib-es/api/types.js +0 -2
- package/lib-es/api/types.js.map +0 -1
- package/lib-es/api/utils.d.ts.map +0 -1
- package/lib-es/api/utils.js +0 -124
- package/lib-es/api/utils.js.map +0 -1
- package/lib-es/logic.d.ts +0 -11
- package/lib-es/logic.d.ts.map +0 -1
- package/lib-es/logic.js +0 -29
- package/lib-es/logic.js.map +0 -1
- package/src/api/mirror.ts +0 -91
- package/src/api/network.test.ts +0 -49
- package/src/api/network.ts +0 -125
- package/src/api/utils.ts +0 -150
- package/src/logic.test.ts +0 -152
- package/src/logic.ts +0 -66
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
import invariant from "invariant";
|
|
2
|
+
import {
|
|
3
|
+
AccountId,
|
|
4
|
+
Hbar,
|
|
5
|
+
HbarUnit,
|
|
6
|
+
TokenAssociateTransaction,
|
|
7
|
+
TransferTransaction,
|
|
8
|
+
} from "@hashgraph/sdk";
|
|
9
|
+
import type { FeeEstimation, Pagination } from "@ledgerhq/coin-framework/api/types";
|
|
10
|
+
import { createApi } from "../api";
|
|
11
|
+
import { HEDERA_TRANSACTION_MODES, TINYBAR_SCALE } from "../constants";
|
|
12
|
+
import { getSyntheticBlock } from "../logic/utils";
|
|
13
|
+
import { MAINNET_TEST_ACCOUNTS } from "../test/fixtures/account.fixture";
|
|
14
|
+
|
|
15
|
+
describe("createApi", () => {
|
|
16
|
+
const api = createApi({});
|
|
17
|
+
|
|
18
|
+
describe("craftTransaction", () => {
|
|
19
|
+
it("returns serialized native coin TransferTransaction", async () => {
|
|
20
|
+
const { transaction: hex } = await api.craftTransaction({
|
|
21
|
+
intentType: "transaction",
|
|
22
|
+
asset: {
|
|
23
|
+
type: "native",
|
|
24
|
+
},
|
|
25
|
+
type: HEDERA_TRANSACTION_MODES.Send,
|
|
26
|
+
amount: BigInt(1 * 10 ** TINYBAR_SCALE),
|
|
27
|
+
sender: MAINNET_TEST_ACCOUNTS.withoutTokens.accountId,
|
|
28
|
+
senderPublicKey: MAINNET_TEST_ACCOUNTS.withoutTokens.publicKey,
|
|
29
|
+
recipient: MAINNET_TEST_ACCOUNTS.withTokens.accountId,
|
|
30
|
+
memo: {
|
|
31
|
+
kind: "text",
|
|
32
|
+
type: "string",
|
|
33
|
+
value: "native transfer",
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const rawTx = TransferTransaction.fromBytes(Buffer.from(hex, "hex"));
|
|
38
|
+
|
|
39
|
+
expect(rawTx).toBeInstanceOf(TransferTransaction);
|
|
40
|
+
invariant(rawTx instanceof TransferTransaction, "TransferTransaction type guard");
|
|
41
|
+
|
|
42
|
+
const sendTransfer = rawTx.hbarTransfers.get(MAINNET_TEST_ACCOUNTS.withoutTokens.accountId);
|
|
43
|
+
const receiveTransfer = rawTx.hbarTransfers.get(MAINNET_TEST_ACCOUNTS.withTokens.accountId);
|
|
44
|
+
|
|
45
|
+
expect(rawTx.hbarTransfers.size).toBe(2);
|
|
46
|
+
expect(sendTransfer).toEqual(Hbar.from(-1, HbarUnit.Hbar));
|
|
47
|
+
expect(receiveTransfer).toEqual(Hbar.from(1, HbarUnit.Hbar));
|
|
48
|
+
expect(rawTx.transactionMemo).toBe("native transfer");
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("returns serialized HTS token TransferTransaction", async () => {
|
|
52
|
+
const { transaction: hex } = await api.craftTransaction({
|
|
53
|
+
intentType: "transaction",
|
|
54
|
+
asset: {
|
|
55
|
+
type: "hts",
|
|
56
|
+
assetReference: "0.0.5022567",
|
|
57
|
+
},
|
|
58
|
+
type: HEDERA_TRANSACTION_MODES.Send,
|
|
59
|
+
amount: BigInt(1),
|
|
60
|
+
sender: MAINNET_TEST_ACCOUNTS.withoutTokens.accountId,
|
|
61
|
+
senderPublicKey: MAINNET_TEST_ACCOUNTS.withoutTokens.publicKey,
|
|
62
|
+
recipient: MAINNET_TEST_ACCOUNTS.withTokens.accountId,
|
|
63
|
+
memo: {
|
|
64
|
+
kind: "text",
|
|
65
|
+
type: "string",
|
|
66
|
+
value: "token transfer",
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const rawTx = TransferTransaction.fromBytes(Buffer.from(hex, "hex"));
|
|
71
|
+
|
|
72
|
+
expect(rawTx).toBeInstanceOf(TransferTransaction);
|
|
73
|
+
invariant(rawTx instanceof TransferTransaction, "TransferTransaction type guard");
|
|
74
|
+
|
|
75
|
+
const tokenTransfers = rawTx.tokenTransfers.get("0.0.5022567");
|
|
76
|
+
const senderTransfer = tokenTransfers?.get(MAINNET_TEST_ACCOUNTS.withoutTokens.accountId);
|
|
77
|
+
const recipientTransfer = tokenTransfers?.get(MAINNET_TEST_ACCOUNTS.withTokens.accountId);
|
|
78
|
+
|
|
79
|
+
// .toString() is used because tokenTransfers values are Long objects
|
|
80
|
+
// this is internal dependency of @hashgraph/sdk, re-exported in newer version
|
|
81
|
+
expect(senderTransfer?.toString()).toEqual("-1");
|
|
82
|
+
expect(recipientTransfer?.toString()).toEqual("1");
|
|
83
|
+
expect(tokenTransfers).not.toBeNull();
|
|
84
|
+
expect(rawTx.transactionMemo).toBe("token transfer");
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it("returns serialized HTS token association transaction", async () => {
|
|
88
|
+
const { transaction: hex } = await api.craftTransaction({
|
|
89
|
+
intentType: "transaction",
|
|
90
|
+
asset: {
|
|
91
|
+
type: "hts",
|
|
92
|
+
assetReference: "0.0.5022567",
|
|
93
|
+
},
|
|
94
|
+
amount: BigInt(0),
|
|
95
|
+
sender: MAINNET_TEST_ACCOUNTS.withoutTokens.accountId,
|
|
96
|
+
senderPublicKey: MAINNET_TEST_ACCOUNTS.withoutTokens.publicKey,
|
|
97
|
+
recipient: MAINNET_TEST_ACCOUNTS.withoutTokens.accountId,
|
|
98
|
+
type: HEDERA_TRANSACTION_MODES.TokenAssociate,
|
|
99
|
+
memo: {
|
|
100
|
+
kind: "text",
|
|
101
|
+
type: "string",
|
|
102
|
+
value: "token association",
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
const rawTx = TokenAssociateTransaction.fromBytes(Buffer.from(hex, "hex"));
|
|
107
|
+
|
|
108
|
+
expect(rawTx).toBeInstanceOf(TokenAssociateTransaction);
|
|
109
|
+
invariant(rawTx instanceof TokenAssociateTransaction, "TokenAssociateTransaction type guard");
|
|
110
|
+
expect(rawTx.accountId).toEqual(
|
|
111
|
+
AccountId.fromString(MAINNET_TEST_ACCOUNTS.withoutTokens.accountId),
|
|
112
|
+
);
|
|
113
|
+
// .toString() is used because sdk.TokenId.fromString() sets `_checksum` to undefined,
|
|
114
|
+
// but tokenIds elements from TokenAssociateTransaction.fromBytes have it set to null
|
|
115
|
+
expect(rawTx.tokenIds?.[0]?.toString()).toEqual("0.0.5022567");
|
|
116
|
+
expect(rawTx.transactionMemo).toBe("token association");
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("applies customFees properly", async () => {
|
|
120
|
+
const customFees: FeeEstimation = {
|
|
121
|
+
value: BigInt(1000),
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
const { transaction: hex } = await api.craftTransaction(
|
|
125
|
+
{
|
|
126
|
+
intentType: "transaction",
|
|
127
|
+
asset: {
|
|
128
|
+
type: "native",
|
|
129
|
+
},
|
|
130
|
+
amount: BigInt(1 * 10 ** TINYBAR_SCALE),
|
|
131
|
+
sender: MAINNET_TEST_ACCOUNTS.withoutTokens.accountId,
|
|
132
|
+
senderPublicKey: MAINNET_TEST_ACCOUNTS.withoutTokens.publicKey,
|
|
133
|
+
recipient: MAINNET_TEST_ACCOUNTS.withTokens.accountId,
|
|
134
|
+
type: HEDERA_TRANSACTION_MODES.Send,
|
|
135
|
+
memo: {
|
|
136
|
+
kind: "text",
|
|
137
|
+
type: "string",
|
|
138
|
+
value: "",
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
customFees,
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
const rawTx = TransferTransaction.fromBytes(Buffer.from(hex, "hex"));
|
|
145
|
+
|
|
146
|
+
expect(rawTx).toBeInstanceOf(TransferTransaction);
|
|
147
|
+
invariant(rawTx instanceof TransferTransaction, "TransferTransaction type guard");
|
|
148
|
+
|
|
149
|
+
expect(rawTx.maxTransactionFee).toEqual(Hbar.from(customFees.value, HbarUnit.Tinybar));
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe("estimateFees", () => {
|
|
154
|
+
it("returns fee for coin transfer transaction", async () => {
|
|
155
|
+
const fees = await api.estimateFees({
|
|
156
|
+
intentType: "transaction",
|
|
157
|
+
asset: {
|
|
158
|
+
type: "native",
|
|
159
|
+
},
|
|
160
|
+
type: HEDERA_TRANSACTION_MODES.Send,
|
|
161
|
+
sender: MAINNET_TEST_ACCOUNTS.withoutTokens.accountId,
|
|
162
|
+
senderPublicKey: MAINNET_TEST_ACCOUNTS.withoutTokens.publicKey,
|
|
163
|
+
amount: BigInt(100),
|
|
164
|
+
recipient: MAINNET_TEST_ACCOUNTS.withTokens.accountId,
|
|
165
|
+
memo: {
|
|
166
|
+
kind: "text",
|
|
167
|
+
type: "string",
|
|
168
|
+
value: "",
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
expect(fees.value).toBeGreaterThanOrEqual(0n);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it("returns fee for token transfer transaction", async () => {
|
|
176
|
+
const fees = await api.estimateFees({
|
|
177
|
+
intentType: "transaction",
|
|
178
|
+
asset: {
|
|
179
|
+
type: "hts",
|
|
180
|
+
assetReference: "0.0.5022567",
|
|
181
|
+
},
|
|
182
|
+
type: HEDERA_TRANSACTION_MODES.Send,
|
|
183
|
+
sender: MAINNET_TEST_ACCOUNTS.withoutTokens.accountId,
|
|
184
|
+
senderPublicKey: MAINNET_TEST_ACCOUNTS.withoutTokens.publicKey,
|
|
185
|
+
amount: BigInt(100),
|
|
186
|
+
recipient: MAINNET_TEST_ACCOUNTS.withTokens.accountId,
|
|
187
|
+
memo: {
|
|
188
|
+
kind: "text",
|
|
189
|
+
type: "string",
|
|
190
|
+
value: "",
|
|
191
|
+
},
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
expect(fees.value).toBeGreaterThanOrEqual(0n);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it("returns fee for token association transaction", async () => {
|
|
198
|
+
const fees = await api.estimateFees({
|
|
199
|
+
intentType: "transaction",
|
|
200
|
+
asset: {
|
|
201
|
+
type: "hts",
|
|
202
|
+
assetReference: "0.0.5022567",
|
|
203
|
+
},
|
|
204
|
+
type: HEDERA_TRANSACTION_MODES.TokenAssociate,
|
|
205
|
+
sender: MAINNET_TEST_ACCOUNTS.withoutTokens.accountId,
|
|
206
|
+
senderPublicKey: MAINNET_TEST_ACCOUNTS.withoutTokens.publicKey,
|
|
207
|
+
amount: BigInt(100),
|
|
208
|
+
recipient: MAINNET_TEST_ACCOUNTS.withTokens.accountId,
|
|
209
|
+
memo: {
|
|
210
|
+
kind: "text",
|
|
211
|
+
type: "string",
|
|
212
|
+
value: "",
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
expect(fees.value).toBeGreaterThanOrEqual(0n);
|
|
217
|
+
});
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
describe("getBalance", () => {
|
|
221
|
+
it("returns zero balance for pristine account", async () => {
|
|
222
|
+
const balances = await api.getBalance(MAINNET_TEST_ACCOUNTS.pristine.accountId);
|
|
223
|
+
|
|
224
|
+
expect(balances.length).toBe(1);
|
|
225
|
+
expect(balances[0].value).toBe(0n);
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it("returns native asset for account without tokens", async () => {
|
|
229
|
+
const balances = await api.getBalance(MAINNET_TEST_ACCOUNTS.withoutTokens.accountId);
|
|
230
|
+
const nativeBalance = balances.filter(b => b.asset.type === "native");
|
|
231
|
+
|
|
232
|
+
expect(nativeBalance.length).toBe(1);
|
|
233
|
+
expect(nativeBalance[0].value).toBeGreaterThan(0n);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it("returns native and token assets for account with tokens", async () => {
|
|
237
|
+
const balances = await api.getBalance(MAINNET_TEST_ACCOUNTS.withTokens.accountId);
|
|
238
|
+
const tokenBalances = balances.filter(b => b.asset.type !== "native");
|
|
239
|
+
|
|
240
|
+
const associatedTokenWithBalance = balances.find(b => {
|
|
241
|
+
return (
|
|
242
|
+
"assetReference" in b.asset &&
|
|
243
|
+
b.asset.assetReference === MAINNET_TEST_ACCOUNTS.withTokens.associatedTokenWithBalance
|
|
244
|
+
);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
const associatedTokenWithoutBalance = balances.find(b => {
|
|
248
|
+
return (
|
|
249
|
+
"assetReference" in b.asset &&
|
|
250
|
+
b.asset.assetReference === MAINNET_TEST_ACCOUNTS.withTokens.associatedTokenWithoutBalance
|
|
251
|
+
);
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
const notAssociatedToken = balances.find(b => {
|
|
255
|
+
return (
|
|
256
|
+
"assetReference" in b.asset &&
|
|
257
|
+
b.asset.assetReference === MAINNET_TEST_ACCOUNTS.withTokens.notAssociatedToken
|
|
258
|
+
);
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
expect(tokenBalances.length).toBeGreaterThan(0);
|
|
262
|
+
expect(associatedTokenWithBalance?.value).toBeGreaterThan(0n);
|
|
263
|
+
expect(associatedTokenWithoutBalance?.value).toBe(0n);
|
|
264
|
+
expect(notAssociatedToken?.value).toBe(undefined);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
describe("lastBlock", () => {
|
|
269
|
+
it("returns the last block information", async () => {
|
|
270
|
+
const lastBlock = await api.lastBlock();
|
|
271
|
+
|
|
272
|
+
expect(lastBlock.height).toBeGreaterThan(0);
|
|
273
|
+
expect(lastBlock.hash?.length).toBe(64);
|
|
274
|
+
expect(lastBlock.time?.getTime()).toBeGreaterThan(0);
|
|
275
|
+
});
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
describe("listOperations", () => {
|
|
279
|
+
it("returns empty array for pristine account", async () => {
|
|
280
|
+
const block = await api.lastBlock();
|
|
281
|
+
const [operations] = await api.listOperations(MAINNET_TEST_ACCOUNTS.pristine.accountId, {
|
|
282
|
+
minHeight: block.height,
|
|
283
|
+
order: "desc",
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
expect(operations).toBeInstanceOf(Array);
|
|
287
|
+
expect(operations.length).toBe(0);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("returns operations with valid synthetic block info", async () => {
|
|
291
|
+
const lastPagingToken = "1753099264.927988000";
|
|
292
|
+
const block = await api.lastBlock();
|
|
293
|
+
const [ops] = await api.listOperations(MAINNET_TEST_ACCOUNTS.withTokens.accountId, {
|
|
294
|
+
minHeight: block.height,
|
|
295
|
+
order: "asc",
|
|
296
|
+
limit: 4,
|
|
297
|
+
lastPagingToken,
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
const expectedSyntheticBlock = getSyntheticBlock(lastPagingToken);
|
|
301
|
+
const blockHeights = ops.map(o => o.tx.block.height);
|
|
302
|
+
|
|
303
|
+
expect(blockHeights).toHaveLength(4);
|
|
304
|
+
expect(blockHeights.every(h => h >= expectedSyntheticBlock.blockHeight)).toBe(true);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
it("returns operations for real account with tokens", async () => {
|
|
308
|
+
const lastPagingToken = "1753099264.927988000";
|
|
309
|
+
const block = await api.lastBlock();
|
|
310
|
+
const [ops] = await api.listOperations(MAINNET_TEST_ACCOUNTS.withTokens.accountId, {
|
|
311
|
+
minHeight: block.height,
|
|
312
|
+
order: "desc",
|
|
313
|
+
limit: 100,
|
|
314
|
+
lastPagingToken,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
const memoTxHash = "WvMcFERtxRsGJqxqGVDYa6JR5PqLgFeJxiSVoimayaWra/AMEJMzC09LhdRLTZ/M";
|
|
318
|
+
const operationWithMemo = ops.find(op => op.tx.hash === memoTxHash);
|
|
319
|
+
const firstTokenAssociateOperations = ops.find(op => op.type === "ASSOCIATE_TOKEN");
|
|
320
|
+
const firstSendTokenOperation = ops.find(o => o.type === "OUT" && o.asset.type !== "native");
|
|
321
|
+
|
|
322
|
+
const hasReceiveHbarOperations = ops.some(o => o.type === "IN" && o.asset.type === "native");
|
|
323
|
+
const hasSendHbarOperations = ops.some(op => op.type === "OUT" && op.asset.type === "native");
|
|
324
|
+
const hasReceiveTokenOperations = ops.some(o => o.type === "IN" && o.asset.type !== "native");
|
|
325
|
+
const hasSendTokenOperations = !!firstSendTokenOperation;
|
|
326
|
+
const hasTokenAssociateOperations = !!firstTokenAssociateOperations;
|
|
327
|
+
const hasFeesOperationForSendToken = ops.some(
|
|
328
|
+
o =>
|
|
329
|
+
o.type === "FEES" &&
|
|
330
|
+
o.asset.type === "native" &&
|
|
331
|
+
o.tx.hash === firstSendTokenOperation?.tx.hash,
|
|
332
|
+
);
|
|
333
|
+
|
|
334
|
+
expect(ops).toBeInstanceOf(Array);
|
|
335
|
+
expect(ops.length).toBeGreaterThanOrEqual(2);
|
|
336
|
+
expect(hasReceiveHbarOperations).toBe(true);
|
|
337
|
+
expect(hasSendHbarOperations).toBe(true);
|
|
338
|
+
expect(hasReceiveTokenOperations).toBe(true);
|
|
339
|
+
expect(hasSendTokenOperations).toBe(true);
|
|
340
|
+
expect(hasFeesOperationForSendToken).toBe(false);
|
|
341
|
+
expect(hasTokenAssociateOperations).toBe(true);
|
|
342
|
+
expect(operationWithMemo?.details).toMatchObject({
|
|
343
|
+
pagingToken: expect.any(String),
|
|
344
|
+
consensusTimestamp: expect.any(String),
|
|
345
|
+
ledgerOpType: expect.any(String),
|
|
346
|
+
memo: expect.any(String),
|
|
347
|
+
});
|
|
348
|
+
expect(firstTokenAssociateOperations?.details).toMatchObject({
|
|
349
|
+
pagingToken: expect.any(String),
|
|
350
|
+
consensusTimestamp: expect.any(String),
|
|
351
|
+
ledgerOpType: expect.any(String),
|
|
352
|
+
associatedTokenId: expect.any(String),
|
|
353
|
+
});
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
it.each(["desc", "asc"] as const)(
|
|
357
|
+
"returns paginated operations for account with high activity (%s)",
|
|
358
|
+
async order => {
|
|
359
|
+
const commonPagination = {
|
|
360
|
+
minHeight: 0,
|
|
361
|
+
limit: 10,
|
|
362
|
+
order,
|
|
363
|
+
} satisfies Pagination;
|
|
364
|
+
|
|
365
|
+
const [page1, pagingToken1] = await api.listOperations(
|
|
366
|
+
MAINNET_TEST_ACCOUNTS.withTokens.accountId,
|
|
367
|
+
commonPagination,
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
const [page2, pagingToken2] = await api.listOperations(
|
|
371
|
+
MAINNET_TEST_ACCOUNTS.withTokens.accountId,
|
|
372
|
+
{
|
|
373
|
+
...commonPagination,
|
|
374
|
+
lastPagingToken: pagingToken1,
|
|
375
|
+
},
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
const firstPage1Timestamp = page1[0]?.tx?.date;
|
|
379
|
+
const firstPage2Timestamp = page2[0]?.tx?.date;
|
|
380
|
+
const lastPage1Timestamp = page1[page1.length - 1]?.tx?.date;
|
|
381
|
+
const lastPage2Timestamp = page2[page2.length - 1]?.tx?.date;
|
|
382
|
+
const page1Hashes = new Set(page1.map(op => op.tx.hash));
|
|
383
|
+
const page2Hashes = new Set(page2.map(op => op.tx.hash));
|
|
384
|
+
const hasOverlap = [...page2Hashes].some(hash => page1Hashes.has(hash));
|
|
385
|
+
|
|
386
|
+
// NOTE: this won't be equal to limit, because single Hedera transaction can generate multiple operations
|
|
387
|
+
expect(page1.length).toBeGreaterThanOrEqual(commonPagination.limit);
|
|
388
|
+
expect(page2.length).toBeGreaterThanOrEqual(commonPagination.limit);
|
|
389
|
+
expect(pagingToken1).not.toBeNull();
|
|
390
|
+
expect(pagingToken2).not.toBeNull();
|
|
391
|
+
expect(hasOverlap).toBe(false);
|
|
392
|
+
expect(firstPage1Timestamp).toBeInstanceOf(Date);
|
|
393
|
+
expect(firstPage2Timestamp).toBeInstanceOf(Date);
|
|
394
|
+
expect(lastPage1Timestamp).toBeInstanceOf(Date);
|
|
395
|
+
expect(lastPage2Timestamp).toBeInstanceOf(Date);
|
|
396
|
+
expect(lastPage1Timestamp > firstPage2Timestamp).toBe(order === "desc");
|
|
397
|
+
expect(firstPage1Timestamp < lastPage2Timestamp).toBe(order === "asc");
|
|
398
|
+
},
|
|
399
|
+
);
|
|
400
|
+
});
|
|
401
|
+
});
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { createApi } from "./index";
|
|
2
|
+
import coinConfig from "../config";
|
|
3
|
+
|
|
4
|
+
describe("createApi", () => {
|
|
5
|
+
it("should set the coin config value", () => {
|
|
6
|
+
const mockSetCoinConfig = jest.spyOn(coinConfig, "setCoinConfig");
|
|
7
|
+
|
|
8
|
+
createApi({});
|
|
9
|
+
const config = coinConfig.getCoinConfig();
|
|
10
|
+
|
|
11
|
+
expect(mockSetCoinConfig).toHaveBeenCalled();
|
|
12
|
+
expect(config).toMatchObject({
|
|
13
|
+
status: { type: "active" },
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it("should return an API object with alpaca api methods", () => {
|
|
18
|
+
const api = createApi({});
|
|
19
|
+
|
|
20
|
+
expect(api.broadcast).toBeInstanceOf(Function);
|
|
21
|
+
expect(api.combine).toBeInstanceOf(Function);
|
|
22
|
+
expect(api.craftTransaction).toBeInstanceOf(Function);
|
|
23
|
+
expect(api.estimateFees).toBeInstanceOf(Function);
|
|
24
|
+
expect(api.getBalance).toBeInstanceOf(Function);
|
|
25
|
+
expect(api.lastBlock).toBeInstanceOf(Function);
|
|
26
|
+
expect(api.listOperations).toBeInstanceOf(Function);
|
|
27
|
+
expect(api.getAssetFromToken).toBeInstanceOf(Function);
|
|
28
|
+
expect(api.getTokenFromAsset).toBeInstanceOf(Function);
|
|
29
|
+
});
|
|
30
|
+
});
|
package/src/api/index.ts
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
Api,
|
|
3
|
+
Block,
|
|
4
|
+
BlockInfo,
|
|
5
|
+
CraftedTransaction,
|
|
6
|
+
Cursor,
|
|
7
|
+
Operation,
|
|
8
|
+
Page,
|
|
9
|
+
Reward,
|
|
10
|
+
Stake,
|
|
11
|
+
TransactionValidation,
|
|
12
|
+
Validator,
|
|
13
|
+
} from "@ledgerhq/coin-framework/api/index";
|
|
14
|
+
import { getCryptoCurrencyById } from "@ledgerhq/cryptoassets/currencies";
|
|
15
|
+
import coinConfig from "../config";
|
|
16
|
+
import {
|
|
17
|
+
broadcast as logicBroadcast,
|
|
18
|
+
combine,
|
|
19
|
+
craftTransaction,
|
|
20
|
+
estimateFees,
|
|
21
|
+
getBalance,
|
|
22
|
+
listOperations as logicListOperations,
|
|
23
|
+
getAssetFromToken,
|
|
24
|
+
getTokenFromAsset,
|
|
25
|
+
lastBlock,
|
|
26
|
+
} from "../logic/index";
|
|
27
|
+
import { mapIntentToSDKOperation, getOperationValue } from "../logic/utils";
|
|
28
|
+
import { apiClient } from "../network/api";
|
|
29
|
+
import type { HederaMemo } from "../types";
|
|
30
|
+
|
|
31
|
+
export function createApi(config: Record<string, never>): Api<HederaMemo> {
|
|
32
|
+
coinConfig.setCoinConfig(() => ({ ...config, status: { type: "active" } }));
|
|
33
|
+
const currency = getCryptoCurrencyById("hedera");
|
|
34
|
+
|
|
35
|
+
return {
|
|
36
|
+
broadcast: async tx => {
|
|
37
|
+
const response = await logicBroadcast(tx);
|
|
38
|
+
return Buffer.from(response.transactionHash).toString("base64");
|
|
39
|
+
},
|
|
40
|
+
combine,
|
|
41
|
+
craftTransaction: async (txIntent, customFees) => {
|
|
42
|
+
const { serializedTx } = await craftTransaction(txIntent, customFees);
|
|
43
|
+
|
|
44
|
+
return {
|
|
45
|
+
transaction: serializedTx,
|
|
46
|
+
};
|
|
47
|
+
},
|
|
48
|
+
craftRawTransaction: (
|
|
49
|
+
_transaction: string,
|
|
50
|
+
_sender: string,
|
|
51
|
+
_publicKey: string,
|
|
52
|
+
_sequence: number,
|
|
53
|
+
): Promise<CraftedTransaction> => {
|
|
54
|
+
throw new Error("craftRawTransaction is not supported");
|
|
55
|
+
},
|
|
56
|
+
estimateFees: async transactionIntent => {
|
|
57
|
+
const operationType = mapIntentToSDKOperation(transactionIntent);
|
|
58
|
+
const estimatedFee = await estimateFees(currency, operationType);
|
|
59
|
+
|
|
60
|
+
return {
|
|
61
|
+
value: BigInt(estimatedFee.toString()),
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
getBalance: address => getBalance(currency, address),
|
|
65
|
+
lastBlock,
|
|
66
|
+
listOperations: async (address, pagination) => {
|
|
67
|
+
const mirrorTokens = await apiClient.getAccountTokens(address);
|
|
68
|
+
const latestAccountOperations = await logicListOperations({
|
|
69
|
+
currency,
|
|
70
|
+
address,
|
|
71
|
+
pagination,
|
|
72
|
+
mirrorTokens,
|
|
73
|
+
fetchAllPages: false,
|
|
74
|
+
skipFeesForTokenOperations: true,
|
|
75
|
+
useEncodedHash: false,
|
|
76
|
+
useSyntheticBlocks: true,
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
const liveOperations = [
|
|
80
|
+
...latestAccountOperations.coinOperations,
|
|
81
|
+
...latestAccountOperations.tokenOperations,
|
|
82
|
+
];
|
|
83
|
+
|
|
84
|
+
const sortedLiveOperations = [...liveOperations].sort((a, b) => {
|
|
85
|
+
const aTime = a.date.getTime();
|
|
86
|
+
const bTime = b.date.getTime();
|
|
87
|
+
return pagination.order === "desc" ? bTime - aTime : aTime - bTime;
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
const alpacaOperations = sortedLiveOperations.map(liveOp => {
|
|
91
|
+
const asset = liveOp.contract
|
|
92
|
+
? {
|
|
93
|
+
type: liveOp.standard ?? "token",
|
|
94
|
+
assetReference: liveOp.contract,
|
|
95
|
+
assetOwner: address,
|
|
96
|
+
}
|
|
97
|
+
: { type: "native" };
|
|
98
|
+
|
|
99
|
+
return {
|
|
100
|
+
id: liveOp.id,
|
|
101
|
+
type: liveOp.type,
|
|
102
|
+
senders: liveOp.senders,
|
|
103
|
+
recipients: liveOp.recipients,
|
|
104
|
+
value: getOperationValue({ asset, operation: liveOp }),
|
|
105
|
+
asset,
|
|
106
|
+
details: {
|
|
107
|
+
...liveOp.extra,
|
|
108
|
+
ledgerOpType: liveOp.type,
|
|
109
|
+
status: liveOp.hasFailed ? "failed" : "success",
|
|
110
|
+
...(asset.type !== "native" && { assetAmount: liveOp.value.toFixed(0) }),
|
|
111
|
+
},
|
|
112
|
+
tx: {
|
|
113
|
+
hash: liveOp.hash,
|
|
114
|
+
fees: BigInt(liveOp.fee.toFixed(0)),
|
|
115
|
+
date: liveOp.date,
|
|
116
|
+
block: {
|
|
117
|
+
height: liveOp.blockHeight ?? 10,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
} satisfies Operation;
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
return [alpacaOperations, latestAccountOperations.nextCursor ?? ""];
|
|
124
|
+
},
|
|
125
|
+
getTokenFromAsset: asset => getTokenFromAsset(currency, asset),
|
|
126
|
+
getAssetFromToken,
|
|
127
|
+
validateIntent: async (_transactionIntent, _customFees): Promise<TransactionValidation> => {
|
|
128
|
+
throw new Error("validateIntent is not supported");
|
|
129
|
+
},
|
|
130
|
+
getSequence: async (_address): Promise<number> => {
|
|
131
|
+
throw new Error("getSequence is not supported");
|
|
132
|
+
},
|
|
133
|
+
getBlock: async (_height): Promise<Block> => {
|
|
134
|
+
throw new Error("getBlock is not supported");
|
|
135
|
+
},
|
|
136
|
+
getBlockInfo: async (_height): Promise<BlockInfo> => {
|
|
137
|
+
throw new Error("getBlockInfo is not supported");
|
|
138
|
+
},
|
|
139
|
+
getStakes: async (_address, _cursor): Promise<Page<Stake>> => {
|
|
140
|
+
throw new Error("getStakes is not supported");
|
|
141
|
+
},
|
|
142
|
+
getRewards: async (_address, _cursor): Promise<Page<Reward>> => {
|
|
143
|
+
throw new Error("getRewards is not supported");
|
|
144
|
+
},
|
|
145
|
+
getValidators(_cursor?: Cursor): Promise<Page<Validator>> {
|
|
146
|
+
throw new Error("getValidators is not supported");
|
|
147
|
+
},
|
|
148
|
+
};
|
|
149
|
+
}
|
package/src/bridge/broadcast.ts
CHANGED
|
@@ -1,18 +1,13 @@
|
|
|
1
|
-
import { Transaction as HederaSDKTransaction } from "@hashgraph/sdk";
|
|
2
1
|
import { AccountBridge, Operation } from "@ledgerhq/types-live";
|
|
3
2
|
import { patchOperationWithHash } from "@ledgerhq/coin-framework/operation";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
3
|
+
import { broadcast as logicBroadcast } from "../logic/broadcast";
|
|
4
|
+
import { base64ToUrlSafeBase64, isValidExtra } from "../logic/utils";
|
|
5
|
+
import type { HederaOperationExtra, Transaction } from "../types";
|
|
6
|
+
import { patchOperationWithExtra } from "./utils";
|
|
8
7
|
|
|
9
8
|
export const broadcast: AccountBridge<Transaction>["broadcast"] = async ({ signedOperation }) => {
|
|
10
9
|
const { signature, operation } = signedOperation;
|
|
11
|
-
|
|
12
|
-
// NOTE: expecting a serialized transaction to be signedOperation.signature (in hex)
|
|
13
|
-
const hederaTransaction = HederaSDKTransaction.fromBytes(Buffer.from(signature, "base64"));
|
|
14
|
-
|
|
15
|
-
const response = await broadcastTransaction(hederaTransaction);
|
|
10
|
+
const response = await logicBroadcast(signature);
|
|
16
11
|
|
|
17
12
|
const base64Hash = Buffer.from(response.transactionHash).toString("base64");
|
|
18
13
|
const base64HashUrlSafe = base64ToUrlSafeBase64(base64Hash);
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import BigNumber from "bignumber.js";
|
|
2
|
+
import { buildOptimisticOperation } from "./buildOptimisticOperation";
|
|
3
|
+
import { HEDERA_OPERATION_TYPES, HEDERA_TRANSACTION_MODES } from "../constants";
|
|
4
|
+
import { estimateFees } from "../logic/estimateFees";
|
|
2
5
|
import { getMockedAccount, getMockedTokenAccount } from "../test/fixtures/account.fixture";
|
|
3
6
|
import { getMockedTokenCurrency } from "../test/fixtures/currency.fixture";
|
|
4
7
|
import { getMockedTransaction } from "../test/fixtures/transaction.fixture";
|
|
5
|
-
import { buildOptimisticOperation } from "./buildOptimisticOperation";
|
|
6
|
-
import { getEstimatedFees } from "./utils";
|
|
7
|
-
import { HEDERA_OPERATION_TYPES, HEDERA_TRANSACTION_KINDS } from "../constants";
|
|
8
8
|
|
|
9
9
|
describe("buildOptimisticOperation", () => {
|
|
10
10
|
let estimatedFees: Record<"crypto" | "associate", BigNumber>;
|
|
@@ -12,8 +12,8 @@ describe("buildOptimisticOperation", () => {
|
|
|
12
12
|
beforeAll(async () => {
|
|
13
13
|
const mockedAccount = getMockedAccount();
|
|
14
14
|
const [crypto, associate] = await Promise.all([
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
estimateFees(mockedAccount.currency, HEDERA_OPERATION_TYPES.CryptoTransfer),
|
|
16
|
+
estimateFees(mockedAccount.currency, HEDERA_OPERATION_TYPES.TokenAssociate),
|
|
17
17
|
]);
|
|
18
18
|
|
|
19
19
|
estimatedFees = { crypto, associate };
|
|
@@ -23,10 +23,10 @@ describe("buildOptimisticOperation", () => {
|
|
|
23
23
|
const mockedAccount = getMockedAccount();
|
|
24
24
|
const mockedToken = getMockedTokenCurrency();
|
|
25
25
|
const mockedTransaction = getMockedTransaction({
|
|
26
|
+
mode: HEDERA_TRANSACTION_MODES.TokenAssociate,
|
|
26
27
|
amount: new BigNumber(0),
|
|
27
28
|
recipient: "0.0.1234",
|
|
28
29
|
properties: {
|
|
29
|
-
name: HEDERA_TRANSACTION_KINDS.TokenAssociate.name,
|
|
30
30
|
token: mockedToken,
|
|
31
31
|
},
|
|
32
32
|
});
|
|
@@ -39,7 +39,7 @@ describe("buildOptimisticOperation", () => {
|
|
|
39
39
|
expect(op.type).toBe("ASSOCIATE_TOKEN");
|
|
40
40
|
expect(op.extra).toEqual({ associatedTokenId: mockedToken.contractAddress });
|
|
41
41
|
expect(op.fee).toEqual(estimatedFees.associate);
|
|
42
|
-
expect(op.senders).toContain(mockedAccount.freshAddress
|
|
42
|
+
expect(op.senders).toContain(mockedAccount.freshAddress);
|
|
43
43
|
expect(op.recipients).toContain("0.0.1234");
|
|
44
44
|
});
|
|
45
45
|
|
|
@@ -58,7 +58,7 @@ describe("buildOptimisticOperation", () => {
|
|
|
58
58
|
expect(op.type).toBe("OUT");
|
|
59
59
|
expect(op.fee).toEqual(estimatedFees.crypto);
|
|
60
60
|
expect(op.value).toEqual(new BigNumber(123));
|
|
61
|
-
expect(op.senders).toContain(mockedAccount.freshAddress
|
|
61
|
+
expect(op.senders).toContain(mockedAccount.freshAddress);
|
|
62
62
|
expect(op.recipients).toContain("0.0.5678");
|
|
63
63
|
});
|
|
64
64
|
|