@ledgerhq/coin-hedera 1.13.0-nightly.2 → 1.13.0-nightly.20251031023756
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 +16 -22
- 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 +25 -12
- package/lib/bridge/synchronisation.js.map +1 -1
- package/lib/bridge/utils.d.ts +2 -14
- package/lib/bridge/utils.d.ts.map +1 -1
- package/lib/bridge/utils.js +26 -148
- 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 +27 -14
- package/lib-es/bridge/synchronisation.js.map +1 -1
- package/lib-es/bridge/utils.d.ts +2 -14
- package/lib-es/bridge/utils.d.ts.map +1 -1
- package/lib-es/bridge/utils.js +22 -140
- 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 +12 -13
- package/src/api/index.integ.test.ts +406 -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 +26 -23
- package/src/bridge/utils.integration.test.ts +23 -269
- package/src/bridge/utils.ts +40 -207
- 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 +205 -0
- package/src/logic/getBalance.ts +42 -0
- package/src/logic/getTokenFromAsset.test.ts +33 -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 +392 -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
package/src/bridge/utils.ts
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
1
|
import BigNumber from "bignumber.js";
|
|
2
|
-
import murmurhash from "imurmurhash";
|
|
3
|
-
import invariant from "invariant";
|
|
4
|
-
import { AccountId } from "@hashgraph/sdk";
|
|
5
|
-
import { InvalidAddress } from "@ledgerhq/errors";
|
|
6
2
|
import type { Account, Operation, TokenAccount } from "@ledgerhq/types-live";
|
|
7
|
-
import cvsApi from "@ledgerhq/live-countervalues/api/index";
|
|
8
|
-
import {
|
|
9
|
-
findCryptoCurrencyById,
|
|
10
|
-
findTokenByAddressInCurrency,
|
|
11
|
-
getFiatCurrencyByTicker,
|
|
12
|
-
listTokensForCryptoCurrency,
|
|
13
|
-
} from "@ledgerhq/cryptoassets";
|
|
14
3
|
import {
|
|
15
4
|
decodeTokenAccountId,
|
|
16
5
|
emptyHistoryCache,
|
|
@@ -19,63 +8,14 @@ import {
|
|
|
19
8
|
isTokenAccount,
|
|
20
9
|
} from "@ledgerhq/coin-framework/account";
|
|
21
10
|
import { encodeOperationId } from "@ledgerhq/coin-framework/operation";
|
|
22
|
-
import type {
|
|
11
|
+
import type { TokenCurrency } from "@ledgerhq/types-cryptoassets";
|
|
23
12
|
import { mergeOps } from "@ledgerhq/coin-framework/bridge/jsHelpers";
|
|
24
|
-
import {
|
|
13
|
+
import { getCryptoAssetsStore } from "@ledgerhq/coin-framework/crypto-assets/index";
|
|
14
|
+
import { HEDERA_OPERATION_TYPES } from "../constants";
|
|
25
15
|
import { estimateMaxSpendable } from "./estimateMaxSpendable";
|
|
26
|
-
import
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import type { HederaMirrorToken } from "../api/types";
|
|
30
|
-
import { HederaRecipientInvalidChecksum } from "../errors";
|
|
31
|
-
import { isTokenAssociateTransaction, isValidExtra } from "../logic";
|
|
32
|
-
import { BASE_USD_FEE_BY_OPERATION_TYPE, HEDERA_OPERATION_TYPES } from "../constants";
|
|
33
|
-
|
|
34
|
-
const ESTIMATED_FEE_SAFETY_RATE = 2;
|
|
35
|
-
|
|
36
|
-
// note: this is currently called frequently by getTransactionStatus; LRU cache prevents duplicated requests
|
|
37
|
-
export const getCurrencyToUSDRate = makeLRUCache(
|
|
38
|
-
async (currency: Currency) => {
|
|
39
|
-
try {
|
|
40
|
-
const [rate] = await cvsApi.fetchLatest([
|
|
41
|
-
{
|
|
42
|
-
from: currency,
|
|
43
|
-
to: getFiatCurrencyByTicker("USD"),
|
|
44
|
-
startDate: new Date(),
|
|
45
|
-
},
|
|
46
|
-
]);
|
|
47
|
-
|
|
48
|
-
invariant(rate, "no value returned from cvs api");
|
|
49
|
-
|
|
50
|
-
return new BigNumber(rate);
|
|
51
|
-
} catch {
|
|
52
|
-
return null;
|
|
53
|
-
}
|
|
54
|
-
},
|
|
55
|
-
currency => currency.ticker,
|
|
56
|
-
seconds(3),
|
|
57
|
-
);
|
|
58
|
-
|
|
59
|
-
export const getEstimatedFees = async (
|
|
60
|
-
account: Account,
|
|
61
|
-
operationType: HEDERA_OPERATION_TYPES,
|
|
62
|
-
): Promise<BigNumber> => {
|
|
63
|
-
try {
|
|
64
|
-
const usdRate = await getCurrencyToUSDRate(account.currency);
|
|
65
|
-
|
|
66
|
-
if (usdRate) {
|
|
67
|
-
return new BigNumber(BASE_USD_FEE_BY_OPERATION_TYPE[operationType])
|
|
68
|
-
.dividedBy(new BigNumber(usdRate))
|
|
69
|
-
.integerValue(BigNumber.ROUND_CEIL)
|
|
70
|
-
.multipliedBy(ESTIMATED_FEE_SAFETY_RATE);
|
|
71
|
-
}
|
|
72
|
-
// eslint-disable-next-line no-empty
|
|
73
|
-
} catch {}
|
|
74
|
-
|
|
75
|
-
// as fees are based on a currency conversion, we stay
|
|
76
|
-
// on the safe side here and double the estimate for "max spendable"
|
|
77
|
-
return new BigNumber("150200").multipliedBy(ESTIMATED_FEE_SAFETY_RATE); // 0.001502 ℏ (as of 2023-03-14)
|
|
78
|
-
};
|
|
16
|
+
import { estimateFees } from "../logic/estimateFees";
|
|
17
|
+
import { isTokenAssociateTransaction, isValidExtra } from "../logic/utils";
|
|
18
|
+
import type { HederaOperationExtra, Transaction, HederaMirrorToken } from "../types";
|
|
79
19
|
|
|
80
20
|
interface CalculateAmountResult {
|
|
81
21
|
amount: BigNumber;
|
|
@@ -91,7 +31,7 @@ const calculateCoinAmount = async ({
|
|
|
91
31
|
transaction: Transaction;
|
|
92
32
|
operationType: HEDERA_OPERATION_TYPES;
|
|
93
33
|
}): Promise<CalculateAmountResult> => {
|
|
94
|
-
const estimatedFees = await
|
|
34
|
+
const estimatedFees = await estimateFees(account.currency, operationType);
|
|
95
35
|
const amount = transaction.useAllAmount
|
|
96
36
|
? await estimateMaxSpendable({ account, transaction })
|
|
97
37
|
: transaction.amount;
|
|
@@ -142,62 +82,30 @@ export const calculateAmount = ({
|
|
|
142
82
|
return calculateCoinAmount({ account, transaction, operationType });
|
|
143
83
|
};
|
|
144
84
|
|
|
145
|
-
// NOTE: convert from the non-url-safe version of base64 to the url-safe version (that the explorer uses)
|
|
146
|
-
export function base64ToUrlSafeBase64(data: string): string {
|
|
147
|
-
// Might be nice to use this alternative if .nvmrc changes to >= Node v14.18.0
|
|
148
|
-
// base64url encoding option isn't supported until then
|
|
149
|
-
// Buffer.from(data, "base64").toString("base64url");
|
|
150
|
-
|
|
151
|
-
return data.replace(/\//g, "_").replace(/\+/g, "-");
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
const simpleSyncHashMemoize: Record<string, string> = {};
|
|
155
|
-
|
|
156
|
-
export const getSyncHash = (
|
|
157
|
-
currency: CryptoCurrency,
|
|
158
|
-
blacklistedTokenIds: string[] = [],
|
|
159
|
-
): string => {
|
|
160
|
-
const tokens = listTokensForCryptoCurrency(currency);
|
|
161
|
-
|
|
162
|
-
const stringToHash =
|
|
163
|
-
currency.id +
|
|
164
|
-
tokens.map(token => token.id + token.contractAddress + token.name + token.ticker).join("") +
|
|
165
|
-
blacklistedTokenIds.join("");
|
|
166
|
-
|
|
167
|
-
if (!simpleSyncHashMemoize[stringToHash]) {
|
|
168
|
-
simpleSyncHashMemoize[stringToHash] = `0x${murmurhash(stringToHash).result().toString(16)}`;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return simpleSyncHashMemoize[stringToHash];
|
|
172
|
-
};
|
|
173
|
-
|
|
174
85
|
export const getSubAccounts = async (
|
|
175
86
|
accountId: string,
|
|
176
87
|
lastTokenOperations: Operation[],
|
|
177
88
|
mirrorTokens: HederaMirrorToken[],
|
|
178
89
|
): Promise<TokenAccount[]> => {
|
|
179
90
|
// Creating a Map of Operations by TokenCurrencies in order to know which TokenAccounts should be synced as well
|
|
180
|
-
const operationsByToken =
|
|
181
|
-
(acc, tokenOperation) => {
|
|
182
|
-
const { token } = decodeTokenAccountId(tokenOperation.accountId);
|
|
183
|
-
if (!token) return acc;
|
|
184
|
-
|
|
185
|
-
const isTokenListedInCAL = findTokenByAddressInCurrency(
|
|
186
|
-
token.contractAddress,
|
|
187
|
-
token.parentCurrency.id,
|
|
188
|
-
);
|
|
189
|
-
if (!isTokenListedInCAL) return acc;
|
|
190
|
-
|
|
191
|
-
if (!acc.has(token)) {
|
|
192
|
-
acc.set(token, []);
|
|
193
|
-
}
|
|
91
|
+
const operationsByToken = new Map<TokenCurrency, Operation[]>();
|
|
194
92
|
|
|
195
|
-
|
|
93
|
+
for (const tokenOperation of lastTokenOperations) {
|
|
94
|
+
const { token } = await decodeTokenAccountId(tokenOperation.accountId);
|
|
95
|
+
if (!token) continue;
|
|
96
|
+
|
|
97
|
+
const isTokenListedInCAL = await getCryptoAssetsStore().findTokenByAddressInCurrency(
|
|
98
|
+
token.contractAddress,
|
|
99
|
+
token.parentCurrency.id,
|
|
100
|
+
);
|
|
101
|
+
if (!isTokenListedInCAL) continue;
|
|
196
102
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
103
|
+
if (!operationsByToken.has(token)) {
|
|
104
|
+
operationsByToken.set(token, []);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
operationsByToken.get(token)?.push(tokenOperation);
|
|
108
|
+
}
|
|
201
109
|
|
|
202
110
|
const subAccounts: TokenAccount[] = [];
|
|
203
111
|
|
|
@@ -234,7 +142,10 @@ export const getSubAccounts = async (
|
|
|
234
142
|
const parentAccountId = accountId;
|
|
235
143
|
const rawBalance = rawToken.balance;
|
|
236
144
|
const balance = new BigNumber(rawBalance);
|
|
237
|
-
const token = findTokenByAddressInCurrency(
|
|
145
|
+
const token = await getCryptoAssetsStore().findTokenByAddressInCurrency(
|
|
146
|
+
rawToken.token_id,
|
|
147
|
+
"hedera",
|
|
148
|
+
);
|
|
238
149
|
|
|
239
150
|
if (!token) {
|
|
240
151
|
continue;
|
|
@@ -265,14 +176,15 @@ export const getSubAccounts = async (
|
|
|
265
176
|
return subAccounts;
|
|
266
177
|
};
|
|
267
178
|
|
|
268
|
-
type CoinOperationForOrphanChildOperation = Operation &
|
|
179
|
+
type CoinOperationForOrphanChildOperation = Operation<HederaOperationExtra> &
|
|
180
|
+
Required<Pick<Operation, "subOperations">>;
|
|
269
181
|
|
|
270
182
|
// create NONE coin operation that will be a parent of an orphan child operation
|
|
271
|
-
const makeCoinOperationForOrphanChildOperation = (
|
|
272
|
-
childOperation: Operation
|
|
273
|
-
): CoinOperationForOrphanChildOperation => {
|
|
183
|
+
const makeCoinOperationForOrphanChildOperation = async (
|
|
184
|
+
childOperation: Operation<HederaOperationExtra>,
|
|
185
|
+
): Promise<CoinOperationForOrphanChildOperation> => {
|
|
274
186
|
const type = "NONE";
|
|
275
|
-
const { accountId } = decodeTokenAccountId(childOperation.accountId);
|
|
187
|
+
const { accountId } = await decodeTokenAccountId(childOperation.accountId);
|
|
276
188
|
const id = encodeOperationId(accountId, childOperation.hash, type);
|
|
277
189
|
|
|
278
190
|
return {
|
|
@@ -298,34 +210,16 @@ const makeCoinOperationForOrphanChildOperation = (
|
|
|
298
210
|
// this util handles:
|
|
299
211
|
// - linking sub operations with coin operations, e.g. token transfer with fee payment
|
|
300
212
|
// - if possible, assigning `extra.associatedTokenId = mirrorToken.tokenId` based on operation's consensus timestamp
|
|
301
|
-
export const prepareOperations = (
|
|
302
|
-
coinOperations: Operation[],
|
|
303
|
-
tokenOperations: Operation[],
|
|
304
|
-
|
|
305
|
-
): Operation[] => {
|
|
213
|
+
export const prepareOperations = async (
|
|
214
|
+
coinOperations: Operation<HederaOperationExtra>[],
|
|
215
|
+
tokenOperations: Operation<HederaOperationExtra>[],
|
|
216
|
+
): Promise<Operation<HederaOperationExtra>[]> => {
|
|
306
217
|
const preparedCoinOperations = coinOperations.map(op => ({ ...op }));
|
|
307
218
|
const preparedTokenOperations = tokenOperations.map(op => ({ ...op }));
|
|
308
219
|
|
|
309
|
-
// loop through coin operations to
|
|
310
|
-
// - enrich ASSOCIATE_TOKEN operations with extra.associatedTokenId
|
|
311
|
-
// - prepare a map of hash => operations
|
|
220
|
+
// loop through coin operations to prepare a map of hash => operations
|
|
312
221
|
const coinOperationsByHash: Record<string, CoinOperationForOrphanChildOperation[]> = {};
|
|
313
222
|
preparedCoinOperations.forEach(op => {
|
|
314
|
-
const extra = isValidExtra(op.extra) ? op.extra : null;
|
|
315
|
-
|
|
316
|
-
if (op.type === "ASSOCIATE_TOKEN" && extra?.consensusTimestamp) {
|
|
317
|
-
const relatedMirrorToken = mirrorTokens.find(t => {
|
|
318
|
-
return t.created_timestamp === extra.consensusTimestamp;
|
|
319
|
-
});
|
|
320
|
-
|
|
321
|
-
if (relatedMirrorToken) {
|
|
322
|
-
op.extra = {
|
|
323
|
-
...extra,
|
|
324
|
-
associatedTokenId: relatedMirrorToken.token_id,
|
|
325
|
-
} satisfies HederaOperationExtra;
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
223
|
if (!coinOperationsByHash[op.hash]) {
|
|
330
224
|
coinOperationsByHash[op.hash] = [];
|
|
331
225
|
}
|
|
@@ -336,13 +230,13 @@ export const prepareOperations = (
|
|
|
336
230
|
|
|
337
231
|
// loop through token operations to potentially copy them as a child operation of a coin operation
|
|
338
232
|
for (const tokenOperation of preparedTokenOperations) {
|
|
339
|
-
const { token } = decodeTokenAccountId(tokenOperation.accountId);
|
|
233
|
+
const { token } = await decodeTokenAccountId(tokenOperation.accountId);
|
|
340
234
|
if (!token) continue;
|
|
341
235
|
|
|
342
236
|
let mainOperations = coinOperationsByHash[tokenOperation.hash];
|
|
343
237
|
|
|
344
238
|
if (!mainOperations?.length) {
|
|
345
|
-
const noneOperation = makeCoinOperationForOrphanChildOperation(tokenOperation);
|
|
239
|
+
const noneOperation = await makeCoinOperationForOrphanChildOperation(tokenOperation);
|
|
346
240
|
mainOperations = [noneOperation];
|
|
347
241
|
preparedCoinOperations.push(noneOperation);
|
|
348
242
|
}
|
|
@@ -456,64 +350,3 @@ export function patchOperationWithExtra(
|
|
|
456
350
|
nftOperations: (operation.nftOperations ?? []).map(op => ({ ...op, extra })),
|
|
457
351
|
};
|
|
458
352
|
}
|
|
459
|
-
|
|
460
|
-
export const checkAccountTokenAssociationStatus = makeLRUCache(
|
|
461
|
-
async (address: string, tokenId: string) => {
|
|
462
|
-
const [parsingError, parsingResult] = safeParseAccountId(address);
|
|
463
|
-
|
|
464
|
-
if (parsingError) {
|
|
465
|
-
throw parsingError;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
const addressWithoutChecksum = parsingResult.accountId;
|
|
469
|
-
const mirrorAccount = await getAccount(addressWithoutChecksum);
|
|
470
|
-
|
|
471
|
-
// auto association is enabled
|
|
472
|
-
if (mirrorAccount.max_automatic_token_associations === -1) {
|
|
473
|
-
return true;
|
|
474
|
-
}
|
|
475
|
-
|
|
476
|
-
const isTokenAssociated = mirrorAccount.balance.tokens.some(token => {
|
|
477
|
-
return token.token_id === tokenId;
|
|
478
|
-
});
|
|
479
|
-
|
|
480
|
-
return isTokenAssociated;
|
|
481
|
-
},
|
|
482
|
-
(accountId, tokenId) => `${accountId}-${tokenId}`,
|
|
483
|
-
seconds(30),
|
|
484
|
-
);
|
|
485
|
-
|
|
486
|
-
export const safeParseAccountId = (
|
|
487
|
-
address: string,
|
|
488
|
-
): [Error, null] | [null, { accountId: string; checksum: string | null }] => {
|
|
489
|
-
const currency = findCryptoCurrencyById("hedera");
|
|
490
|
-
const currencyName = currency?.name ?? "Hedera";
|
|
491
|
-
|
|
492
|
-
try {
|
|
493
|
-
const accountId = AccountId.fromString(address);
|
|
494
|
-
|
|
495
|
-
// verify checksum if present
|
|
496
|
-
// FIXME: migrate to EntityIdHelper methods once SDK is upgraded:
|
|
497
|
-
// https://github.com/hiero-ledger/hiero-sdk-js/blob/main/src/EntityIdHelper.js#L197
|
|
498
|
-
// https://github.com/hiero-ledger/hiero-sdk-js/blob/main/src/EntityIdHelper.js#L446
|
|
499
|
-
const checksum: string | null = address.split("-")[1] ?? null;
|
|
500
|
-
if (checksum) {
|
|
501
|
-
const client = getHederaClient();
|
|
502
|
-
const recipientWithChecksum = accountId.toStringWithChecksum(client);
|
|
503
|
-
const expectedChecksum = recipientWithChecksum.split("-")[1];
|
|
504
|
-
|
|
505
|
-
if (checksum !== expectedChecksum) {
|
|
506
|
-
return [new HederaRecipientInvalidChecksum(), null];
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
const result = {
|
|
511
|
-
accountId: accountId.toString(),
|
|
512
|
-
checksum,
|
|
513
|
-
};
|
|
514
|
-
|
|
515
|
-
return [null, result];
|
|
516
|
-
} catch (err) {
|
|
517
|
-
return [new InvalidAddress("", { currencyName }), null];
|
|
518
|
-
}
|
|
519
|
-
};
|
package/src/config.ts
ADDED
package/src/constants.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Internal types
|
|
3
|
-
* These can be
|
|
2
|
+
* Internal types to distinguish custom Hedera transaction behaviors.
|
|
3
|
+
* These can be used in transaction.mode and used to route specific preparation logic.
|
|
4
4
|
*/
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
} as const satisfies Record<string, Record<string, unknown> & { name: string }>;
|
|
5
|
+
export enum HEDERA_TRANSACTION_MODES {
|
|
6
|
+
Send = "send",
|
|
7
|
+
TokenAssociate = "token-associate",
|
|
8
|
+
}
|
|
10
9
|
|
|
11
10
|
/**
|
|
12
11
|
* Enum representing the supported Hedera operation types for fee estimation
|
|
@@ -17,7 +16,14 @@ export enum HEDERA_OPERATION_TYPES {
|
|
|
17
16
|
TokenAssociate = "TokenAssociate",
|
|
18
17
|
}
|
|
19
18
|
|
|
20
|
-
const TINYBAR_SCALE = 8;
|
|
19
|
+
export const TINYBAR_SCALE = 8;
|
|
20
|
+
|
|
21
|
+
export const ESTIMATED_FEE_SAFETY_RATE = 2;
|
|
22
|
+
|
|
23
|
+
// old value moved from https://github.com/LedgerHQ/ledger-live/blob/8447b68b7c6f1e7ccd4aa9db4da0e6c8de36a88e/libs/coin-modules/coin-hedera/src/bridge/utils.ts#L77
|
|
24
|
+
export const DEFAULT_TINYBAR_FEE = 150200;
|
|
25
|
+
|
|
26
|
+
export const SYNTHETIC_BLOCK_WINDOW_SECONDS = 10;
|
|
21
27
|
|
|
22
28
|
/**
|
|
23
29
|
* https://docs.hedera.com/hedera/networks/mainnet/fees
|
|
@@ -25,7 +31,7 @@ const TINYBAR_SCALE = 8;
|
|
|
25
31
|
* These are Hedera's estimated fee costs in USD, scaled to tinybars (1 HBAR = 10^8 tinybars),
|
|
26
32
|
* so they can be converted into actual HBAR amounts based on current USD/crypto rates.
|
|
27
33
|
*
|
|
28
|
-
* Used in fee estimation logic (
|
|
34
|
+
* Used in fee estimation logic (estimateFees function) to determine whether an account
|
|
29
35
|
* has sufficient balance to cover the cost of a transaction (e.g. token association).
|
|
30
36
|
*/
|
|
31
37
|
export const BASE_USD_FEE_BY_OPERATION_TYPE = {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { AccountLike, Account } from "@ledgerhq/types-live";
|
|
2
|
-
import type { Transaction, TransactionStatus } from "./types";
|
|
3
2
|
import type { CommonDeviceTransactionField as DeviceTransactionField } from "@ledgerhq/coin-framework/transaction/common";
|
|
4
|
-
import { isTokenAssociateTransaction } from "./logic";
|
|
3
|
+
import { isTokenAssociateTransaction } from "./logic/utils";
|
|
4
|
+
import type { Transaction, TransactionStatus } from "./types";
|
|
5
5
|
|
|
6
6
|
async function getDeviceTransactionConfig({
|
|
7
7
|
transaction,
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { broadcast } from "./broadcast";
|
|
2
|
+
import { rpcClient } from "../network/rpc";
|
|
3
|
+
import { deserializeTransaction } from "./utils";
|
|
4
|
+
|
|
5
|
+
jest.mock("../network/rpc");
|
|
6
|
+
jest.mock("./utils");
|
|
7
|
+
|
|
8
|
+
describe("broadcast", () => {
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
jest.clearAllMocks();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("should deserialize and broadcast a transaction successfully", async () => {
|
|
14
|
+
const txWithSignature = "serialized-transaction-with-signature";
|
|
15
|
+
const mockDeserializedTx = { someProperty: "mockTransaction" } as any;
|
|
16
|
+
const mockResponse = { transactionId: "mock-transaction-id" } as any;
|
|
17
|
+
|
|
18
|
+
(deserializeTransaction as jest.Mock).mockReturnValue(mockDeserializedTx);
|
|
19
|
+
(rpcClient.broadcastTransaction as jest.Mock).mockResolvedValue(mockResponse);
|
|
20
|
+
|
|
21
|
+
const result = await broadcast(txWithSignature);
|
|
22
|
+
|
|
23
|
+
expect(deserializeTransaction).toHaveBeenCalledTimes(1);
|
|
24
|
+
expect(deserializeTransaction).toHaveBeenCalledWith(txWithSignature);
|
|
25
|
+
expect(rpcClient.broadcastTransaction).toHaveBeenCalledTimes(1);
|
|
26
|
+
expect(rpcClient.broadcastTransaction).toHaveBeenCalledWith(mockDeserializedTx);
|
|
27
|
+
expect(result).toBe(mockResponse);
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("should propagate errors from deserializeTransaction", async () => {
|
|
31
|
+
const txWithSignature = "serialized-transaction-with-signature";
|
|
32
|
+
const error = new Error("Deserialization error");
|
|
33
|
+
|
|
34
|
+
(deserializeTransaction as jest.Mock).mockImplementation(() => {
|
|
35
|
+
throw error;
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
await expect(broadcast(txWithSignature)).rejects.toThrow(error);
|
|
39
|
+
expect(deserializeTransaction).toHaveBeenCalledTimes(1);
|
|
40
|
+
expect(deserializeTransaction).toHaveBeenCalledWith(txWithSignature);
|
|
41
|
+
expect(rpcClient.broadcastTransaction).not.toHaveBeenCalled();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it("should propagate errors from broadcastTransaction", async () => {
|
|
45
|
+
const txWithSignature = "serialized-transaction-with-signature";
|
|
46
|
+
const mockDeserializedTx = { someProperty: "mockTransaction" } as any;
|
|
47
|
+
const error = new Error("Network error");
|
|
48
|
+
|
|
49
|
+
(deserializeTransaction as jest.Mock).mockReturnValue(mockDeserializedTx);
|
|
50
|
+
(rpcClient.broadcastTransaction as jest.Mock).mockRejectedValue(error);
|
|
51
|
+
|
|
52
|
+
await expect(broadcast(txWithSignature)).rejects.toThrow(error);
|
|
53
|
+
expect(deserializeTransaction).toHaveBeenCalledTimes(1);
|
|
54
|
+
expect(deserializeTransaction).toHaveBeenCalledWith(txWithSignature);
|
|
55
|
+
expect(rpcClient.broadcastTransaction).toHaveBeenCalledTimes(1);
|
|
56
|
+
expect(rpcClient.broadcastTransaction).toHaveBeenCalledWith(mockDeserializedTx);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TransactionResponse } from "@hashgraph/sdk";
|
|
2
|
+
import { rpcClient } from "../network/rpc";
|
|
3
|
+
import { deserializeTransaction } from "./utils";
|
|
4
|
+
|
|
5
|
+
export const broadcast = async (txWithSignature: string): Promise<TransactionResponse> => {
|
|
6
|
+
const hederaTransaction = deserializeTransaction(txWithSignature);
|
|
7
|
+
return await rpcClient.broadcastTransaction(hederaTransaction);
|
|
8
|
+
};
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { PublicKey } from "@hashgraph/sdk";
|
|
2
|
+
import { combine } from "./combine";
|
|
3
|
+
import { deserializeSignature, deserializeTransaction, serializeTransaction } from "./utils";
|
|
4
|
+
|
|
5
|
+
jest.mock("./utils");
|
|
6
|
+
jest.mock("@hashgraph/sdk");
|
|
7
|
+
|
|
8
|
+
describe("combine", () => {
|
|
9
|
+
beforeEach(() => {
|
|
10
|
+
jest.clearAllMocks();
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
it("should combine transaction with signature successfully", () => {
|
|
14
|
+
const tx = "serialized-transaction";
|
|
15
|
+
const signature = "serialized-signature";
|
|
16
|
+
const publicKey = "public-key-string";
|
|
17
|
+
|
|
18
|
+
const mockDeserializedTx = { addSignature: jest.fn() } as any;
|
|
19
|
+
const mockBufferSignature = Buffer.from("mock-signature");
|
|
20
|
+
const mockBufferPublicKey = { key: "mock-public-key" } as any;
|
|
21
|
+
const mockSerializedTxWithSignature = "serialized-transaction-with-signature";
|
|
22
|
+
|
|
23
|
+
(deserializeTransaction as jest.Mock).mockReturnValue(mockDeserializedTx);
|
|
24
|
+
(deserializeSignature as jest.Mock).mockReturnValue(mockBufferSignature);
|
|
25
|
+
(PublicKey.fromString as jest.Mock).mockReturnValue(mockBufferPublicKey);
|
|
26
|
+
(serializeTransaction as jest.Mock).mockReturnValue(mockSerializedTxWithSignature);
|
|
27
|
+
|
|
28
|
+
const result = combine(tx, signature, publicKey);
|
|
29
|
+
|
|
30
|
+
expect(deserializeTransaction).toHaveBeenCalledTimes(1);
|
|
31
|
+
expect(deserializeTransaction).toHaveBeenCalledWith(tx);
|
|
32
|
+
expect(deserializeSignature).toHaveBeenCalledTimes(1);
|
|
33
|
+
expect(deserializeSignature).toHaveBeenCalledWith(signature);
|
|
34
|
+
expect(PublicKey.fromString).toHaveBeenCalledTimes(1);
|
|
35
|
+
expect(PublicKey.fromString).toHaveBeenCalledWith(publicKey);
|
|
36
|
+
expect(mockDeserializedTx.addSignature).toHaveBeenCalledTimes(1);
|
|
37
|
+
expect(mockDeserializedTx.addSignature).toHaveBeenCalledWith(
|
|
38
|
+
mockBufferPublicKey,
|
|
39
|
+
mockBufferSignature,
|
|
40
|
+
);
|
|
41
|
+
expect(serializeTransaction).toHaveBeenCalledTimes(1);
|
|
42
|
+
expect(serializeTransaction).toHaveBeenCalledWith(mockDeserializedTx);
|
|
43
|
+
expect(result).toBe(mockSerializedTxWithSignature);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("should throw an error when public key is not provided", () => {
|
|
47
|
+
const tx = "serialized-transaction";
|
|
48
|
+
const signature = "serialized-signature";
|
|
49
|
+
|
|
50
|
+
expect(() => combine(tx, signature, undefined)).toThrow();
|
|
51
|
+
expect(deserializeTransaction).not.toHaveBeenCalled();
|
|
52
|
+
expect(deserializeSignature).not.toHaveBeenCalled();
|
|
53
|
+
expect(PublicKey.fromString).not.toHaveBeenCalled();
|
|
54
|
+
expect(serializeTransaction).not.toHaveBeenCalled();
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it("should propagate errors from deserializeTransaction", () => {
|
|
58
|
+
const tx = "serialized-transaction";
|
|
59
|
+
const signature = "serialized-signature";
|
|
60
|
+
const publicKey = "public-key-string";
|
|
61
|
+
const error = new Error("Deserialization error");
|
|
62
|
+
|
|
63
|
+
(deserializeTransaction as jest.Mock).mockImplementation(() => {
|
|
64
|
+
throw error;
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
expect(() => combine(tx, signature, publicKey)).toThrow(error);
|
|
68
|
+
expect(deserializeTransaction).toHaveBeenCalledTimes(1);
|
|
69
|
+
expect(deserializeTransaction).toHaveBeenCalledWith(tx);
|
|
70
|
+
expect(deserializeSignature).not.toHaveBeenCalled();
|
|
71
|
+
expect(PublicKey.fromString).not.toHaveBeenCalled();
|
|
72
|
+
expect(serializeTransaction).not.toHaveBeenCalled();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it("should propagate errors from deserializeSignature", () => {
|
|
76
|
+
const tx = "serialized-transaction";
|
|
77
|
+
const signature = "serialized-signature";
|
|
78
|
+
const publicKey = "public-key-string";
|
|
79
|
+
const mockDeserializedTx = { addSignature: jest.fn() } as any;
|
|
80
|
+
const error = new Error("Signature deserialization error");
|
|
81
|
+
|
|
82
|
+
(deserializeTransaction as jest.Mock).mockReturnValue(mockDeserializedTx);
|
|
83
|
+
(deserializeSignature as jest.Mock).mockImplementation(() => {
|
|
84
|
+
throw error;
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
expect(() => combine(tx, signature, publicKey)).toThrow(error);
|
|
88
|
+
expect(deserializeTransaction).toHaveBeenCalledTimes(1);
|
|
89
|
+
expect(deserializeTransaction).toHaveBeenCalledWith(tx);
|
|
90
|
+
expect(deserializeSignature).toHaveBeenCalledTimes(1);
|
|
91
|
+
expect(deserializeSignature).toHaveBeenCalledWith(signature);
|
|
92
|
+
expect(PublicKey.fromString).not.toHaveBeenCalled();
|
|
93
|
+
expect(serializeTransaction).not.toHaveBeenCalled();
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it("should propagate errors from PublicKey.fromString", () => {
|
|
97
|
+
const tx = "serialized-transaction";
|
|
98
|
+
const signature = "serialized-signature";
|
|
99
|
+
const publicKey = "invalid-public-key";
|
|
100
|
+
const mockDeserializedTx = { addSignature: jest.fn() } as any;
|
|
101
|
+
const mockBufferSignature = Buffer.from("mock-signature");
|
|
102
|
+
const error = new Error("Invalid public key");
|
|
103
|
+
|
|
104
|
+
(deserializeTransaction as jest.Mock).mockReturnValue(mockDeserializedTx);
|
|
105
|
+
(deserializeSignature as jest.Mock).mockReturnValue(mockBufferSignature);
|
|
106
|
+
(PublicKey.fromString as jest.Mock).mockImplementation(() => {
|
|
107
|
+
throw error;
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
expect(() => combine(tx, signature, publicKey)).toThrow(error);
|
|
111
|
+
expect(deserializeTransaction).toHaveBeenCalledTimes(1);
|
|
112
|
+
expect(deserializeTransaction).toHaveBeenCalledWith(tx);
|
|
113
|
+
expect(deserializeSignature).toHaveBeenCalledTimes(1);
|
|
114
|
+
expect(deserializeSignature).toHaveBeenCalledWith(signature);
|
|
115
|
+
expect(PublicKey.fromString).toHaveBeenCalledTimes(1);
|
|
116
|
+
expect(PublicKey.fromString).toHaveBeenCalledWith(publicKey);
|
|
117
|
+
expect(serializeTransaction).not.toHaveBeenCalled();
|
|
118
|
+
});
|
|
119
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import invariant from "invariant";
|
|
2
|
+
import { PublicKey } from "@hashgraph/sdk";
|
|
3
|
+
import { deserializeSignature, deserializeTransaction, serializeTransaction } from "./utils";
|
|
4
|
+
|
|
5
|
+
export function combine(tx: string, signature: string, publicKey?: string): string {
|
|
6
|
+
invariant(publicKey, "hedera: public key is required to combine the transaction");
|
|
7
|
+
|
|
8
|
+
const hederaTransaction = deserializeTransaction(tx);
|
|
9
|
+
const bufferSignature = deserializeSignature(signature);
|
|
10
|
+
const bufferPublicKey = PublicKey.fromString(publicKey);
|
|
11
|
+
hederaTransaction.addSignature(bufferPublicKey, bufferSignature);
|
|
12
|
+
|
|
13
|
+
return serializeTransaction(hederaTransaction);
|
|
14
|
+
}
|