@ledgerhq/coin-stellar 6.26.0 → 6.26.1
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/.oxlintrc.json +7 -0
- package/CHANGELOG.md +6 -0
- package/LICENSE +194 -0
- package/knip.json +12 -0
- package/lib/api/index.d.ts +5 -5
- package/lib/api/index.d.ts.map +1 -1
- package/lib/api/index.js +12 -10
- package/lib/api/index.js.map +1 -1
- package/lib/config.d.ts +1 -1
- package/lib/config.d.ts.map +1 -1
- package/lib/config.js +2 -0
- package/lib/config.js.map +1 -1
- package/lib/constants.d.ts.map +1 -1
- package/lib/constants.js +3 -1
- package/lib/constants.js.map +1 -1
- package/lib/logic/broadcast.d.ts.map +1 -1
- package/lib/logic/broadcast.js +2 -0
- package/lib/logic/broadcast.js.map +1 -1
- package/lib/logic/combine.d.ts +1 -1
- package/lib/logic/combine.d.ts.map +1 -1
- package/lib/logic/combine.js +2 -0
- package/lib/logic/combine.js.map +1 -1
- package/lib/logic/common.d.ts +1 -1
- package/lib/logic/common.d.ts.map +1 -1
- package/lib/logic/common.js +4 -2
- package/lib/logic/common.js.map +1 -1
- package/lib/logic/craftTransaction.d.ts +1 -1
- package/lib/logic/craftTransaction.d.ts.map +1 -1
- package/lib/logic/craftTransaction.js +10 -8
- package/lib/logic/craftTransaction.js.map +1 -1
- package/lib/logic/estimateFees.d.ts.map +1 -1
- package/lib/logic/estimateFees.js +2 -0
- package/lib/logic/estimateFees.js.map +1 -1
- package/lib/logic/getBalance.d.ts +1 -1
- package/lib/logic/getBalance.d.ts.map +1 -1
- package/lib/logic/getBalance.js +4 -2
- package/lib/logic/getBalance.js.map +1 -1
- package/lib/logic/getBlock.d.ts +1 -1
- package/lib/logic/getBlock.d.ts.map +1 -1
- package/lib/logic/getBlock.js +39 -34
- package/lib/logic/getBlock.js.map +1 -1
- package/lib/logic/getBlockInfo.d.ts +1 -1
- package/lib/logic/getBlockInfo.d.ts.map +1 -1
- package/lib/logic/getBlockInfo.js +2 -0
- package/lib/logic/getBlockInfo.js.map +1 -1
- package/lib/logic/index.d.ts +12 -12
- package/lib/logic/index.d.ts.map +1 -1
- package/lib/logic/index.js +2 -0
- package/lib/logic/index.js.map +1 -1
- package/lib/logic/lastBlock.d.ts +1 -1
- package/lib/logic/lastBlock.d.ts.map +1 -1
- package/lib/logic/lastBlock.js +2 -0
- package/lib/logic/lastBlock.js.map +1 -1
- package/lib/logic/listOperations.d.ts +1 -1
- package/lib/logic/listOperations.d.ts.map +1 -1
- package/lib/logic/listOperations.js +6 -4
- package/lib/logic/listOperations.js.map +1 -1
- package/lib/logic/sdkWrapper.d.ts +1 -1
- package/lib/logic/sdkWrapper.d.ts.map +1 -1
- package/lib/logic/sdkWrapper.js +2 -0
- package/lib/logic/sdkWrapper.js.map +1 -1
- package/lib/logic/utils.d.ts.map +1 -1
- package/lib/logic/utils.js +4 -2
- package/lib/logic/utils.js.map +1 -1
- package/lib/logic/validateAddress.d.ts +1 -1
- package/lib/logic/validateAddress.d.ts.map +1 -1
- package/lib/logic/validateAddress.js +2 -0
- package/lib/logic/validateAddress.js.map +1 -1
- package/lib/logic/validateIntent.d.ts +2 -2
- package/lib/logic/validateIntent.d.ts.map +1 -1
- package/lib/logic/validateIntent.js +21 -19
- package/lib/logic/validateIntent.js.map +1 -1
- package/lib/logic/validateMemo.d.ts +1 -1
- package/lib/logic/validateMemo.d.ts.map +1 -1
- package/lib/logic/validateMemo.js +7 -5
- package/lib/logic/validateMemo.js.map +1 -1
- package/lib/network/horizon.d.ts +6 -7
- package/lib/network/horizon.d.ts.map +1 -1
- package/lib/network/horizon.js +71 -68
- package/lib/network/horizon.js.map +1 -1
- package/lib/network/horizonLedgerErrors.d.ts.map +1 -1
- package/lib/network/horizonLedgerErrors.js +5 -3
- package/lib/network/horizonLedgerErrors.js.map +1 -1
- package/lib/network/index.d.ts +1 -1
- package/lib/network/index.d.ts.map +1 -1
- package/lib/network/index.js +2 -0
- package/lib/network/index.js.map +1 -1
- package/lib/network/serialization.d.ts +6 -4
- package/lib/network/serialization.d.ts.map +1 -1
- package/lib/network/serialization.js +95 -91
- package/lib/network/serialization.js.map +1 -1
- package/lib/polyfill.d.ts.map +1 -1
- package/lib/polyfill.js +6 -4
- package/lib/polyfill.js.map +1 -1
- package/lib/supportedFeatures.d.ts +1 -1
- package/lib/supportedFeatures.d.ts.map +1 -1
- package/lib/supportedFeatures.js +3 -1
- package/lib/supportedFeatures.js.map +1 -1
- package/lib/types/errors.d.ts.map +1 -1
- package/lib/types/errors.js +14 -12
- package/lib/types/errors.js.map +1 -1
- package/lib/types/index.d.ts +2 -2
- 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/types/model.d.ts +6 -6
- package/lib/types/model.d.ts.map +1 -1
- package/lib/types/model.js +7 -5
- package/lib/types/model.js.map +1 -1
- package/lib-es/api/index.d.ts +5 -5
- package/lib-es/api/index.d.ts.map +1 -1
- package/lib-es/api/index.js +20 -18
- package/lib-es/api/index.js.map +1 -1
- package/lib-es/config.d.ts +1 -1
- package/lib-es/config.d.ts.map +1 -1
- package/lib-es/config.js +3 -1
- package/lib-es/config.js.map +1 -1
- package/lib-es/constants.d.ts.map +1 -1
- package/lib-es/constants.js +3 -1
- package/lib-es/constants.js.map +1 -1
- package/lib-es/logic/broadcast.d.ts.map +1 -1
- package/lib-es/logic/broadcast.js +3 -1
- package/lib-es/logic/broadcast.js.map +1 -1
- package/lib-es/logic/combine.d.ts +1 -1
- package/lib-es/logic/combine.d.ts.map +1 -1
- package/lib-es/logic/combine.js +3 -1
- package/lib-es/logic/combine.js.map +1 -1
- package/lib-es/logic/common.d.ts +1 -1
- package/lib-es/logic/common.d.ts.map +1 -1
- package/lib-es/logic/common.js +5 -3
- package/lib-es/logic/common.js.map +1 -1
- package/lib-es/logic/craftTransaction.d.ts +1 -1
- package/lib-es/logic/craftTransaction.d.ts.map +1 -1
- package/lib-es/logic/craftTransaction.js +15 -13
- package/lib-es/logic/craftTransaction.js.map +1 -1
- package/lib-es/logic/estimateFees.d.ts.map +1 -1
- package/lib-es/logic/estimateFees.js +3 -1
- package/lib-es/logic/estimateFees.js.map +1 -1
- package/lib-es/logic/getBalance.d.ts +1 -1
- package/lib-es/logic/getBalance.d.ts.map +1 -1
- package/lib-es/logic/getBalance.js +5 -3
- package/lib-es/logic/getBalance.js.map +1 -1
- package/lib-es/logic/getBlock.d.ts +1 -1
- package/lib-es/logic/getBlock.d.ts.map +1 -1
- package/lib-es/logic/getBlock.js +42 -37
- package/lib-es/logic/getBlock.js.map +1 -1
- package/lib-es/logic/getBlockInfo.d.ts +1 -1
- package/lib-es/logic/getBlockInfo.d.ts.map +1 -1
- package/lib-es/logic/getBlockInfo.js +3 -1
- package/lib-es/logic/getBlockInfo.js.map +1 -1
- package/lib-es/logic/index.d.ts +12 -12
- package/lib-es/logic/index.d.ts.map +1 -1
- package/lib-es/logic/index.js +14 -12
- package/lib-es/logic/index.js.map +1 -1
- package/lib-es/logic/lastBlock.d.ts +1 -1
- package/lib-es/logic/lastBlock.d.ts.map +1 -1
- package/lib-es/logic/lastBlock.js +3 -1
- package/lib-es/logic/lastBlock.js.map +1 -1
- package/lib-es/logic/listOperations.d.ts +1 -1
- package/lib-es/logic/listOperations.d.ts.map +1 -1
- package/lib-es/logic/listOperations.js +7 -5
- package/lib-es/logic/listOperations.js.map +1 -1
- package/lib-es/logic/sdkWrapper.d.ts +1 -1
- package/lib-es/logic/sdkWrapper.d.ts.map +1 -1
- package/lib-es/logic/sdkWrapper.js +4 -2
- package/lib-es/logic/sdkWrapper.js.map +1 -1
- package/lib-es/logic/utils.d.ts.map +1 -1
- package/lib-es/logic/utils.js +6 -4
- package/lib-es/logic/utils.js.map +1 -1
- package/lib-es/logic/validateAddress.d.ts +1 -1
- package/lib-es/logic/validateAddress.d.ts.map +1 -1
- package/lib-es/logic/validateAddress.js +3 -1
- package/lib-es/logic/validateAddress.js.map +1 -1
- package/lib-es/logic/validateIntent.d.ts +2 -2
- package/lib-es/logic/validateIntent.d.ts.map +1 -1
- package/lib-es/logic/validateIntent.js +30 -28
- package/lib-es/logic/validateIntent.js.map +1 -1
- package/lib-es/logic/validateMemo.d.ts +1 -1
- package/lib-es/logic/validateMemo.d.ts.map +1 -1
- package/lib-es/logic/validateMemo.js +8 -6
- package/lib-es/logic/validateMemo.js.map +1 -1
- package/lib-es/network/horizon.d.ts +6 -7
- package/lib-es/network/horizon.d.ts.map +1 -1
- package/lib-es/network/horizon.js +80 -77
- package/lib-es/network/horizon.js.map +1 -1
- package/lib-es/network/horizonLedgerErrors.d.ts.map +1 -1
- package/lib-es/network/horizonLedgerErrors.js +7 -5
- package/lib-es/network/horizonLedgerErrors.js.map +1 -1
- package/lib-es/network/index.d.ts +1 -1
- package/lib-es/network/index.d.ts.map +1 -1
- package/lib-es/network/index.js +3 -1
- package/lib-es/network/index.js.map +1 -1
- package/lib-es/network/serialization.d.ts +6 -4
- package/lib-es/network/serialization.d.ts.map +1 -1
- package/lib-es/network/serialization.js +97 -95
- package/lib-es/network/serialization.js.map +1 -1
- package/lib-es/polyfill.d.ts.map +1 -1
- package/lib-es/polyfill.js +7 -5
- package/lib-es/polyfill.js.map +1 -1
- package/lib-es/supportedFeatures.d.ts +1 -1
- package/lib-es/supportedFeatures.d.ts.map +1 -1
- package/lib-es/supportedFeatures.js +3 -1
- package/lib-es/supportedFeatures.js.map +1 -1
- package/lib-es/types/errors.d.ts.map +1 -1
- package/lib-es/types/errors.js +15 -13
- package/lib-es/types/errors.js.map +1 -1
- package/lib-es/types/index.d.ts +2 -2
- package/lib-es/types/index.d.ts.map +1 -1
- package/lib-es/types/index.js +4 -2
- package/lib-es/types/index.js.map +1 -1
- package/lib-es/types/model.d.ts +6 -6
- package/lib-es/types/model.d.ts.map +1 -1
- package/lib-es/types/model.js +7 -5
- package/lib-es/types/model.js.map +1 -1
- package/package.json +13 -16
- package/src/api/index.integ.test.ts +165 -162
- package/src/api/index.test.ts +106 -103
- package/src/api/index.ts +49 -46
- package/src/api/index_error.test.ts +48 -25
- package/src/config.ts +15 -12
- package/src/constants.ts +4 -1
- package/src/globals.d.ts +7 -5
- package/src/logic/broadcast.integ.test.ts +22 -19
- package/src/logic/broadcast.ts +5 -2
- package/src/logic/combine.test.ts +18 -15
- package/src/logic/combine.ts +8 -5
- package/src/logic/common.ts +9 -6
- package/src/logic/craftTransaction.test.ts +76 -75
- package/src/logic/craftTransaction.ts +46 -43
- package/src/logic/estimateFees.ts +6 -3
- package/src/logic/getBalance.test.ts +31 -28
- package/src/logic/getBalance.ts +13 -10
- package/src/logic/getBlock.integ.test.ts +40 -39
- package/src/logic/getBlock.test.ts +462 -415
- package/src/logic/getBlock.ts +142 -127
- package/src/logic/getBlockInfo.test.ts +72 -69
- package/src/logic/getBlockInfo.ts +15 -12
- package/src/logic/index.ts +15 -12
- package/src/logic/lastBlock.ts +6 -3
- package/src/logic/listOperations.ts +14 -11
- package/src/logic/listOperations.unit.test.ts +212 -209
- package/src/logic/networkWrappers.test.ts +32 -29
- package/src/logic/sdkWrapper.ts +19 -16
- package/src/logic/utils.ts +13 -10
- package/src/logic/validateAddress.test.ts +21 -18
- package/src/logic/validateAddress.ts +7 -4
- package/src/logic/validateIntent.test.ts +62 -59
- package/src/logic/validateIntent.ts +87 -84
- package/src/logic/validateMemo.test.ts +50 -47
- package/src/logic/validateMemo.ts +16 -13
- package/src/network/broadcastTransaction.test.ts +60 -60
- package/src/network/fetchLedgerOperations.unit.test.ts +155 -0
- package/src/network/horizon.integ.test.ts +45 -42
- package/src/network/horizon.test.ts +17 -14
- package/src/network/horizon.ts +279 -281
- package/src/network/horizon.unit.test.ts +238 -237
- package/src/network/horizonLedgerErrors.test.ts +81 -78
- package/src/network/horizonLedgerErrors.ts +22 -19
- package/src/network/index.ts +4 -1
- package/src/network/registerHorizonInterceptors.test.ts +163 -160
- package/src/network/serialization.ts +232 -227
- package/src/network/serialization.unit.test.ts +801 -798
- package/src/polyfill.ts +18 -15
- package/src/supportedFeatures.ts +6 -3
- package/src/types/errors.ts +33 -32
- package/src/types/index.ts +5 -2
- package/src/types/model.ts +55 -52
- package/tsconfig.json +1 -1
- package/.unimportedrc.json +0 -17
- package/LICENSE.txt +0 -21
- package/src/network/fetchLedgerOperations.nock.unit.test.ts +0 -156
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
1
|
+
// SPDX-FileCopyrightText: © 2026 LEDGER SAS
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
import type { RawOperation } from '../types'
|
|
5
|
+
import { BadResponseError, Horizon, NotFoundError } from '@stellar/stellar-sdk'
|
|
6
|
+
import coinConfig, { type StellarCoinConfig } from '../config'
|
|
7
|
+
import { NetworkCongestionLevel } from '../types/model'
|
|
6
8
|
import {
|
|
7
9
|
broadcastTransaction,
|
|
8
10
|
fetchAllLedgerOperations,
|
|
@@ -10,148 +12,149 @@ import {
|
|
|
10
12
|
fetchLedgerRecord,
|
|
11
13
|
fetchOperations,
|
|
12
14
|
getLastBlock,
|
|
13
|
-
} from
|
|
15
|
+
} from './horizon'
|
|
16
|
+
import * as serialization from './serialization'
|
|
14
17
|
|
|
15
|
-
jest.mock(
|
|
16
|
-
const actual = jest.requireActual<typeof import(
|
|
18
|
+
jest.mock('./serialization', () => {
|
|
19
|
+
const actual = jest.requireActual<typeof import('./serialization')>('./serialization')
|
|
17
20
|
return {
|
|
18
21
|
...actual,
|
|
19
22
|
rawOperationsToOperations: jest.fn(),
|
|
20
|
-
}
|
|
21
|
-
})
|
|
23
|
+
}
|
|
24
|
+
})
|
|
22
25
|
|
|
23
26
|
const rawOperationsToOperationsMock =
|
|
24
27
|
serialization.rawOperationsToOperations as jest.MockedFunction<
|
|
25
28
|
typeof serialization.rawOperationsToOperations
|
|
26
|
-
|
|
29
|
+
>
|
|
27
30
|
|
|
28
|
-
const TEST_HORIZON_URL =
|
|
31
|
+
const TEST_HORIZON_URL = 'https://horizon-stellar-unit-test.invalid/'
|
|
29
32
|
|
|
30
33
|
const signedTxFixture =
|
|
31
|
-
|
|
34
|
+
'AAAAAgAAAABRUCgFba+DTbei2ifpyYt5w2Hh0VyZ+X9fayjIDne7YAAAAGQCkDOGAAAABQAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAQAAAACEIuPfWXgM8WhyqjrpFdIcGV1SUVhMzPUm4YspNHF60QAAAAAAAAAAALkd2QAAAAAAAAABDne7YAAAAEAASzsT/yDIfCfEDstkfnznXjiN7rNd7PkKQEn+rRIFm9EHoirGfHipWoBdYMrc6ixQD/0y0of1piSid8TLiFAB'
|
|
32
35
|
|
|
33
36
|
function baseCoinConfig(overrides: Partial<StellarCoinConfig> = {}): StellarCoinConfig {
|
|
34
37
|
return {
|
|
35
|
-
status: { type:
|
|
38
|
+
status: { type: 'active' },
|
|
36
39
|
explorer: { url: TEST_HORIZON_URL, fetchLimit: 100 },
|
|
37
40
|
useStaticFees: true,
|
|
38
41
|
enableNetworkLogs: false,
|
|
39
42
|
...overrides,
|
|
40
|
-
} as StellarCoinConfig
|
|
43
|
+
} as StellarCoinConfig
|
|
41
44
|
}
|
|
42
45
|
|
|
43
46
|
const HORIZON_SERVER_SPY_METHODS = [
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
] as const
|
|
47
|
+
'ledgers',
|
|
48
|
+
'operations',
|
|
49
|
+
'feeStats',
|
|
50
|
+
'submitTransaction',
|
|
51
|
+
] as const
|
|
49
52
|
|
|
50
53
|
function restoreHorizonServerPrototypeSpies(): void {
|
|
51
|
-
const proto = Horizon.Server.prototype as unknown as Record<string, unknown
|
|
54
|
+
const proto = Horizon.Server.prototype as unknown as Record<string, unknown>
|
|
52
55
|
for (const key of HORIZON_SERVER_SPY_METHODS) {
|
|
53
|
-
const fn = proto[key]
|
|
56
|
+
const fn = proto[key]
|
|
54
57
|
if (jest.isMockFunction(fn)) {
|
|
55
|
-
fn.mockRestore()
|
|
58
|
+
fn.mockRestore()
|
|
56
59
|
}
|
|
57
60
|
}
|
|
58
61
|
}
|
|
59
62
|
|
|
60
63
|
function opBuilder(partial: Partial<RawOperation> & { paging_token: string }): RawOperation {
|
|
61
|
-
const { paging_token, ...rest } = partial
|
|
64
|
+
const { paging_token, ...rest } = partial
|
|
62
65
|
return {
|
|
63
|
-
id:
|
|
66
|
+
id: '1',
|
|
64
67
|
paging_token,
|
|
65
|
-
source_account:
|
|
68
|
+
source_account: 'GSOURCEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
|
66
69
|
transaction_successful: true,
|
|
67
|
-
created_at:
|
|
68
|
-
type:
|
|
69
|
-
transaction_hash:
|
|
70
|
+
created_at: '2020-01-01T00:00:00Z',
|
|
71
|
+
type: 'payment',
|
|
72
|
+
transaction_hash: 'txh',
|
|
70
73
|
...rest,
|
|
71
|
-
} as RawOperation
|
|
74
|
+
} as RawOperation
|
|
72
75
|
}
|
|
73
76
|
|
|
74
|
-
describe(
|
|
75
|
-
let originalGetCoinConfig: () => StellarCoinConfig
|
|
77
|
+
describe('horizon.ts (unit, spies)', () => {
|
|
78
|
+
let originalGetCoinConfig: () => StellarCoinConfig
|
|
76
79
|
|
|
77
80
|
beforeAll(() => {
|
|
78
|
-
originalGetCoinConfig = coinConfig.getCoinConfig
|
|
79
|
-
coinConfig.setCoinConfig(() => baseCoinConfig())
|
|
80
|
-
})
|
|
81
|
+
originalGetCoinConfig = coinConfig.getCoinConfig
|
|
82
|
+
coinConfig.setCoinConfig(() => baseCoinConfig())
|
|
83
|
+
})
|
|
81
84
|
|
|
82
85
|
afterAll(() => {
|
|
83
|
-
coinConfig.setCoinConfig(originalGetCoinConfig)
|
|
84
|
-
})
|
|
86
|
+
coinConfig.setCoinConfig(originalGetCoinConfig)
|
|
87
|
+
})
|
|
85
88
|
|
|
86
89
|
beforeEach(() => {
|
|
87
|
-
restoreHorizonServerPrototypeSpies()
|
|
88
|
-
rawOperationsToOperationsMock.mockReset()
|
|
90
|
+
restoreHorizonServerPrototypeSpies()
|
|
91
|
+
rawOperationsToOperationsMock.mockReset()
|
|
89
92
|
rawOperationsToOperationsMock.mockImplementation(
|
|
90
|
-
jest.requireActual<typeof import(
|
|
91
|
-
.rawOperationsToOperations
|
|
92
|
-
)
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
describe(
|
|
96
|
-
it(
|
|
97
|
-
jest.spyOn(Horizon.Server.prototype,
|
|
93
|
+
jest.requireActual<typeof import('./serialization')>('./serialization')
|
|
94
|
+
.rawOperationsToOperations
|
|
95
|
+
)
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
describe('fetchLedgerRecord', () => {
|
|
99
|
+
it('maps NotFoundError to Stellar ledger not found message', async () => {
|
|
100
|
+
jest.spyOn(Horizon.Server.prototype, 'ledgers').mockReturnValue({
|
|
98
101
|
ledger: jest.fn().mockReturnValue({
|
|
99
|
-
call: jest.fn().mockRejectedValue(new NotFoundError(
|
|
102
|
+
call: jest.fn().mockRejectedValue(new NotFoundError('not found', {})),
|
|
100
103
|
}),
|
|
101
|
-
} as unknown as ReturnType<Horizon.Server[
|
|
104
|
+
} as unknown as ReturnType<Horizon.Server['ledgers']>)
|
|
102
105
|
|
|
103
|
-
await expect(fetchLedgerRecord(999)).rejects.toThrow(
|
|
104
|
-
})
|
|
106
|
+
await expect(fetchLedgerRecord(999)).rejects.toThrow('Stellar ledger 999 not found')
|
|
107
|
+
})
|
|
105
108
|
|
|
106
|
-
it(
|
|
107
|
-
const ledger = { sequence: 7, hash:
|
|
108
|
-
jest.spyOn(Horizon.Server.prototype,
|
|
109
|
+
it('returns ledger record on success', async () => {
|
|
110
|
+
const ledger = { sequence: 7, hash: 'h'.repeat(64), closed_at: '2015-07-20T20:27:50Z' }
|
|
111
|
+
jest.spyOn(Horizon.Server.prototype, 'ledgers').mockReturnValue({
|
|
109
112
|
ledger: jest.fn().mockReturnValue({
|
|
110
113
|
call: jest.fn().mockResolvedValue(ledger),
|
|
111
114
|
}),
|
|
112
|
-
} as unknown as ReturnType<Horizon.Server[
|
|
115
|
+
} as unknown as ReturnType<Horizon.Server['ledgers']>)
|
|
113
116
|
|
|
114
|
-
const rec = await fetchLedgerRecord(7)
|
|
115
|
-
expect(rec.sequence).toBe(7)
|
|
116
|
-
expect(rec.hash).toBe(ledger.hash)
|
|
117
|
-
})
|
|
118
|
-
})
|
|
117
|
+
const rec = await fetchLedgerRecord(7)
|
|
118
|
+
expect(rec.sequence).toBe(7)
|
|
119
|
+
expect(rec.hash).toBe(ledger.hash)
|
|
120
|
+
})
|
|
121
|
+
})
|
|
119
122
|
|
|
120
|
-
describe(
|
|
121
|
-
it(
|
|
122
|
-
jest.spyOn(Horizon.Server.prototype,
|
|
123
|
+
describe('fetchAllLedgerOperations', () => {
|
|
124
|
+
it('maps NotFoundError to Stellar ledger not found message', async () => {
|
|
125
|
+
jest.spyOn(Horizon.Server.prototype, 'operations').mockReturnValue({
|
|
123
126
|
forLedger: jest.fn().mockReturnThis(),
|
|
124
127
|
includeFailed: jest.fn().mockReturnThis(),
|
|
125
128
|
join: jest.fn().mockReturnThis(),
|
|
126
129
|
order: jest.fn().mockReturnThis(),
|
|
127
130
|
limit: jest.fn().mockReturnValue({
|
|
128
|
-
call: jest.fn().mockRejectedValue(new NotFoundError(
|
|
131
|
+
call: jest.fn().mockRejectedValue(new NotFoundError('missing', {})),
|
|
129
132
|
}),
|
|
130
|
-
} as unknown as ReturnType<Horizon.Server[
|
|
133
|
+
} as unknown as ReturnType<Horizon.Server['operations']>)
|
|
131
134
|
|
|
132
|
-
await expect(fetchAllLedgerOperations(4242)).rejects.toThrow(
|
|
133
|
-
})
|
|
135
|
+
await expect(fetchAllLedgerOperations(4242)).rejects.toThrow('Stellar ledger 4242 not found')
|
|
136
|
+
})
|
|
134
137
|
|
|
135
|
-
describe(
|
|
138
|
+
describe('with fetchLimit=2', () => {
|
|
136
139
|
beforeEach(() => {
|
|
137
140
|
coinConfig.setCoinConfig(() =>
|
|
138
|
-
baseCoinConfig({ explorer: { url: TEST_HORIZON_URL, fetchLimit: 2 } })
|
|
139
|
-
)
|
|
140
|
-
})
|
|
141
|
+
baseCoinConfig({ explorer: { url: TEST_HORIZON_URL, fetchLimit: 2 } })
|
|
142
|
+
)
|
|
143
|
+
})
|
|
141
144
|
|
|
142
145
|
afterEach(() => {
|
|
143
|
-
coinConfig.setCoinConfig(() => baseCoinConfig())
|
|
144
|
-
})
|
|
146
|
+
coinConfig.setCoinConfig(() => baseCoinConfig())
|
|
147
|
+
})
|
|
145
148
|
|
|
146
|
-
it(
|
|
147
|
-
const op1 = opBuilder({ paging_token:
|
|
148
|
-
const op2 = opBuilder({ paging_token:
|
|
149
|
-
const secondPage = { records: [] as RawOperation[] }
|
|
149
|
+
it('paginates when first page is full then next page is empty', async () => {
|
|
150
|
+
const op1 = opBuilder({ paging_token: '1', id: 'a' })
|
|
151
|
+
const op2 = opBuilder({ paging_token: '2', id: 'b' })
|
|
152
|
+
const secondPage = { records: [] as RawOperation[] }
|
|
150
153
|
const firstPage = {
|
|
151
154
|
records: [op1, op2],
|
|
152
155
|
next: jest.fn().mockResolvedValue(secondPage),
|
|
153
|
-
}
|
|
154
|
-
jest.spyOn(Horizon.Server.prototype,
|
|
156
|
+
}
|
|
157
|
+
jest.spyOn(Horizon.Server.prototype, 'operations').mockReturnValue({
|
|
155
158
|
forLedger: jest.fn().mockReturnThis(),
|
|
156
159
|
includeFailed: jest.fn().mockReturnThis(),
|
|
157
160
|
join: jest.fn().mockReturnThis(),
|
|
@@ -159,45 +162,45 @@ describe("horizon.ts (unit, spies)", () => {
|
|
|
159
162
|
limit: jest.fn().mockReturnValue({
|
|
160
163
|
call: jest.fn().mockResolvedValue(firstPage),
|
|
161
164
|
}),
|
|
162
|
-
} as unknown as ReturnType<Horizon.Server[
|
|
163
|
-
|
|
164
|
-
const out = await fetchAllLedgerOperations(10)
|
|
165
|
-
expect(out).toHaveLength(2)
|
|
166
|
-
expect(firstPage.next).toHaveBeenCalledTimes(1)
|
|
167
|
-
})
|
|
168
|
-
})
|
|
169
|
-
})
|
|
170
|
-
|
|
171
|
-
describe(
|
|
172
|
-
it(
|
|
173
|
-
jest.spyOn(Horizon.Server.prototype,
|
|
165
|
+
} as unknown as ReturnType<Horizon.Server['operations']>)
|
|
166
|
+
|
|
167
|
+
const out = await fetchAllLedgerOperations(10)
|
|
168
|
+
expect(out).toHaveLength(2)
|
|
169
|
+
expect(firstPage.next).toHaveBeenCalledTimes(1)
|
|
170
|
+
})
|
|
171
|
+
})
|
|
172
|
+
})
|
|
173
|
+
|
|
174
|
+
describe('fetchOperations', () => {
|
|
175
|
+
it('throws LedgerAPI4xx with status 429 when Horizon returns too many requests', async () => {
|
|
176
|
+
jest.spyOn(Horizon.Server.prototype, 'operations').mockReturnValue({
|
|
174
177
|
forAccount: jest.fn().mockReturnThis(),
|
|
175
178
|
limit: jest.fn().mockReturnThis(),
|
|
176
179
|
order: jest.fn().mockReturnThis(),
|
|
177
180
|
cursor: jest.fn().mockReturnThis(),
|
|
178
181
|
includeFailed: jest.fn().mockReturnThis(),
|
|
179
182
|
join: jest.fn().mockReturnValue({
|
|
180
|
-
call: jest.fn().mockRejectedValue(new Error(
|
|
183
|
+
call: jest.fn().mockRejectedValue(new Error('too many requests')),
|
|
181
184
|
}),
|
|
182
|
-
} as unknown as ReturnType<Horizon.Server[
|
|
185
|
+
} as unknown as ReturnType<Horizon.Server['operations']>)
|
|
183
186
|
|
|
184
187
|
await expect(
|
|
185
188
|
fetchOperations({
|
|
186
|
-
accountId:
|
|
187
|
-
addr:
|
|
189
|
+
accountId: 'aid',
|
|
190
|
+
addr: 'GADDRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
|
188
191
|
minHeight: 0,
|
|
189
|
-
order:
|
|
192
|
+
order: 'asc',
|
|
190
193
|
cursor: undefined,
|
|
191
|
-
})
|
|
192
|
-
).rejects.toEqual(expect.objectContaining({ name:
|
|
193
|
-
})
|
|
194
|
+
})
|
|
195
|
+
).rejects.toEqual(expect.objectContaining({ name: 'LedgerAPI4xx', status: 429 }))
|
|
196
|
+
})
|
|
194
197
|
|
|
195
|
-
it(
|
|
196
|
-
const rawA = opBuilder({ paging_token:
|
|
197
|
-
const rawB = opBuilder({ paging_token:
|
|
198
|
-
rawOperationsToOperationsMock.mockResolvedValue([{ type:
|
|
198
|
+
it('sets next cursor to empty when Horizon returns fewer records than the fetch limit', async () => {
|
|
199
|
+
const rawA = opBuilder({ paging_token: 'pt-a', id: '1' })
|
|
200
|
+
const rawB = opBuilder({ paging_token: 'pt-b', id: '2' })
|
|
201
|
+
rawOperationsToOperationsMock.mockResolvedValue([{ type: 'mock-op' } as never])
|
|
199
202
|
|
|
200
|
-
jest.spyOn(Horizon.Server.prototype,
|
|
203
|
+
jest.spyOn(Horizon.Server.prototype, 'operations').mockReturnValue({
|
|
201
204
|
forAccount: jest.fn().mockReturnThis(),
|
|
202
205
|
limit: jest.fn().mockReturnThis(),
|
|
203
206
|
order: jest.fn().mockReturnThis(),
|
|
@@ -206,38 +209,38 @@ describe("horizon.ts (unit, spies)", () => {
|
|
|
206
209
|
join: jest.fn().mockReturnValue({
|
|
207
210
|
call: jest.fn().mockResolvedValue({ records: [rawA, rawB] }),
|
|
208
211
|
}),
|
|
209
|
-
} as unknown as ReturnType<Horizon.Server[
|
|
212
|
+
} as unknown as ReturnType<Horizon.Server['operations']>)
|
|
210
213
|
|
|
211
214
|
// fetchLimit defaults to 100, Horizon returned 2 records → incomplete page → no next cursor
|
|
212
215
|
const page = await fetchOperations({
|
|
213
|
-
accountId:
|
|
214
|
-
addr:
|
|
216
|
+
accountId: 'aid',
|
|
217
|
+
addr: 'GADDRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
|
215
218
|
minHeight: 100,
|
|
216
|
-
order:
|
|
219
|
+
order: 'desc',
|
|
217
220
|
cursor: undefined,
|
|
218
|
-
})
|
|
219
|
-
expect(page.next).toBe(
|
|
220
|
-
expect(page.items).toHaveLength(1)
|
|
221
|
-
})
|
|
221
|
+
})
|
|
222
|
+
expect(page.next).toBe('')
|
|
223
|
+
expect(page.items).toHaveLength(1)
|
|
224
|
+
})
|
|
222
225
|
|
|
223
|
-
describe(
|
|
226
|
+
describe('with fetchLimit=2', () => {
|
|
224
227
|
beforeEach(() => {
|
|
225
228
|
coinConfig.setCoinConfig(() =>
|
|
226
|
-
baseCoinConfig({ explorer: { url: TEST_HORIZON_URL, fetchLimit: 2 } })
|
|
227
|
-
)
|
|
228
|
-
})
|
|
229
|
+
baseCoinConfig({ explorer: { url: TEST_HORIZON_URL, fetchLimit: 2 } })
|
|
230
|
+
)
|
|
231
|
+
})
|
|
229
232
|
|
|
230
233
|
afterEach(() => {
|
|
231
|
-
coinConfig.setCoinConfig(() => baseCoinConfig())
|
|
232
|
-
})
|
|
234
|
+
coinConfig.setCoinConfig(() => baseCoinConfig())
|
|
235
|
+
})
|
|
233
236
|
|
|
234
|
-
it(
|
|
235
|
-
const rawA = opBuilder({ paging_token:
|
|
236
|
-
const rawB = opBuilder({ paging_token:
|
|
237
|
+
it('continues pagination when unsupported ops are filtered from a full page', async () => {
|
|
238
|
+
const rawA = opBuilder({ paging_token: 'pt-a', id: '1' })
|
|
239
|
+
const rawB = opBuilder({ paging_token: 'pt-b', id: '2' })
|
|
237
240
|
// Only 1 op survives filtering (e.g. the other was an unsupported type)
|
|
238
|
-
rawOperationsToOperationsMock.mockResolvedValue([{ type:
|
|
241
|
+
rawOperationsToOperationsMock.mockResolvedValue([{ type: 'mock-op' } as never])
|
|
239
242
|
|
|
240
|
-
jest.spyOn(Horizon.Server.prototype,
|
|
243
|
+
jest.spyOn(Horizon.Server.prototype, 'operations').mockReturnValue({
|
|
241
244
|
forAccount: jest.fn().mockReturnThis(),
|
|
242
245
|
limit: jest.fn().mockReturnThis(),
|
|
243
246
|
order: jest.fn().mockReturnThis(),
|
|
@@ -246,25 +249,25 @@ describe("horizon.ts (unit, spies)", () => {
|
|
|
246
249
|
join: jest.fn().mockReturnValue({
|
|
247
250
|
call: jest.fn().mockResolvedValue({ records: [rawA, rawB] }),
|
|
248
251
|
}),
|
|
249
|
-
} as unknown as ReturnType<Horizon.Server[
|
|
252
|
+
} as unknown as ReturnType<Horizon.Server['operations']>)
|
|
250
253
|
|
|
251
254
|
const page = await fetchOperations({
|
|
252
|
-
accountId:
|
|
253
|
-
addr:
|
|
255
|
+
accountId: 'aid',
|
|
256
|
+
addr: 'GADDRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
|
254
257
|
minHeight: 0,
|
|
255
|
-
order:
|
|
258
|
+
order: 'desc',
|
|
256
259
|
cursor: undefined,
|
|
257
|
-
})
|
|
258
|
-
expect(page.next).toBe(
|
|
259
|
-
expect(page.items).toHaveLength(1)
|
|
260
|
-
})
|
|
260
|
+
})
|
|
261
|
+
expect(page.next).toBe('pt-b')
|
|
262
|
+
expect(page.items).toHaveLength(1)
|
|
263
|
+
})
|
|
261
264
|
|
|
262
|
-
it(
|
|
263
|
-
const rawA = opBuilder({ paging_token:
|
|
265
|
+
it('stops pagination when Horizon returns fewer records than fetchLimit', async () => {
|
|
266
|
+
const rawA = opBuilder({ paging_token: 'pt-a', id: '1' })
|
|
264
267
|
// 1 record < fetchLimit of 2 → last page
|
|
265
|
-
rawOperationsToOperationsMock.mockResolvedValue([{ type:
|
|
268
|
+
rawOperationsToOperationsMock.mockResolvedValue([{ type: 'mock-op' } as never])
|
|
266
269
|
|
|
267
|
-
jest.spyOn(Horizon.Server.prototype,
|
|
270
|
+
jest.spyOn(Horizon.Server.prototype, 'operations').mockReturnValue({
|
|
268
271
|
forAccount: jest.fn().mockReturnThis(),
|
|
269
272
|
limit: jest.fn().mockReturnThis(),
|
|
270
273
|
order: jest.fn().mockReturnThis(),
|
|
@@ -273,162 +276,160 @@ describe("horizon.ts (unit, spies)", () => {
|
|
|
273
276
|
join: jest.fn().mockReturnValue({
|
|
274
277
|
call: jest.fn().mockResolvedValue({ records: [rawA] }),
|
|
275
278
|
}),
|
|
276
|
-
} as unknown as ReturnType<Horizon.Server[
|
|
279
|
+
} as unknown as ReturnType<Horizon.Server['operations']>)
|
|
277
280
|
|
|
278
281
|
const page = await fetchOperations({
|
|
279
|
-
accountId:
|
|
280
|
-
addr:
|
|
282
|
+
accountId: 'aid',
|
|
283
|
+
addr: 'GADDRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
|
281
284
|
minHeight: 0,
|
|
282
|
-
order:
|
|
285
|
+
order: 'desc',
|
|
283
286
|
cursor: undefined,
|
|
284
|
-
})
|
|
285
|
-
expect(page.next).toBe(
|
|
286
|
-
expect(page.items).toHaveLength(1)
|
|
287
|
-
})
|
|
287
|
+
})
|
|
288
|
+
expect(page.next).toBe('')
|
|
289
|
+
expect(page.items).toHaveLength(1)
|
|
290
|
+
})
|
|
288
291
|
|
|
289
|
-
it(
|
|
290
|
-
const rawA = opBuilder({ paging_token:
|
|
291
|
-
const rawB = opBuilder({ paging_token:
|
|
292
|
+
it('returns empty items with cursor when all ops on a full page are filtered out', async () => {
|
|
293
|
+
const rawA = opBuilder({ paging_token: 'pt-a', id: '1' })
|
|
294
|
+
const rawB = opBuilder({ paging_token: 'pt-b', id: '2' })
|
|
292
295
|
|
|
293
296
|
// All ops filtered out (e.g. unsupported types or below minHeight)
|
|
294
|
-
rawOperationsToOperationsMock.mockResolvedValue([])
|
|
297
|
+
rawOperationsToOperationsMock.mockResolvedValue([])
|
|
295
298
|
|
|
296
|
-
const callMock = jest.fn().mockResolvedValueOnce({ records: [rawA, rawB] })
|
|
299
|
+
const callMock = jest.fn().mockResolvedValueOnce({ records: [rawA, rawB] })
|
|
297
300
|
|
|
298
|
-
jest.spyOn(Horizon.Server.prototype,
|
|
301
|
+
jest.spyOn(Horizon.Server.prototype, 'operations').mockReturnValue({
|
|
299
302
|
forAccount: jest.fn().mockReturnThis(),
|
|
300
303
|
limit: jest.fn().mockReturnThis(),
|
|
301
304
|
order: jest.fn().mockReturnThis(),
|
|
302
305
|
cursor: jest.fn().mockReturnThis(),
|
|
303
306
|
includeFailed: jest.fn().mockReturnThis(),
|
|
304
307
|
join: jest.fn().mockReturnValue({ call: callMock }),
|
|
305
|
-
} as unknown as ReturnType<Horizon.Server[
|
|
308
|
+
} as unknown as ReturnType<Horizon.Server['operations']>)
|
|
306
309
|
|
|
307
310
|
const page = await fetchOperations({
|
|
308
|
-
accountId:
|
|
309
|
-
addr:
|
|
311
|
+
accountId: 'aid',
|
|
312
|
+
addr: 'GADDRAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA',
|
|
310
313
|
minHeight: 999999,
|
|
311
|
-
order:
|
|
314
|
+
order: 'desc',
|
|
312
315
|
cursor: undefined,
|
|
313
|
-
})
|
|
316
|
+
})
|
|
314
317
|
// Returns empty items with cursor — caller handles pagination
|
|
315
|
-
expect(page.items).toHaveLength(0)
|
|
316
|
-
expect(page.next).toBe(
|
|
317
|
-
expect(callMock).toHaveBeenCalledTimes(1)
|
|
318
|
-
})
|
|
319
|
-
})
|
|
320
|
-
})
|
|
321
|
-
|
|
322
|
-
describe(
|
|
318
|
+
expect(page.items).toHaveLength(0)
|
|
319
|
+
expect(page.next).toBe('pt-b')
|
|
320
|
+
expect(callMock).toHaveBeenCalledTimes(1)
|
|
321
|
+
})
|
|
322
|
+
})
|
|
323
|
+
})
|
|
324
|
+
|
|
325
|
+
describe('fetchBaseFee', () => {
|
|
323
326
|
beforeEach(() => {
|
|
324
|
-
coinConfig.setCoinConfig(() => baseCoinConfig({ useStaticFees: false }))
|
|
325
|
-
})
|
|
327
|
+
coinConfig.setCoinConfig(() => baseCoinConfig({ useStaticFees: false }))
|
|
328
|
+
})
|
|
326
329
|
|
|
327
330
|
afterEach(() => {
|
|
328
|
-
coinConfig.setCoinConfig(() => baseCoinConfig())
|
|
329
|
-
})
|
|
331
|
+
coinConfig.setCoinConfig(() => baseCoinConfig())
|
|
332
|
+
})
|
|
330
333
|
|
|
331
334
|
test.each([
|
|
332
|
-
[
|
|
333
|
-
[
|
|
334
|
-
[
|
|
335
|
-
])(
|
|
336
|
-
jest.spyOn(Horizon.Server.prototype,
|
|
335
|
+
['0.4', 'low usage -> LOW', NetworkCongestionLevel.LOW],
|
|
336
|
+
['0.6', 'medium usage -> MEDIUM', NetworkCongestionLevel.MEDIUM],
|
|
337
|
+
['0.9', 'high usage -> HIGH', NetworkCongestionLevel.HIGH],
|
|
338
|
+
])('ledger_capacity_usage %s (%s)', async (usage, _label, expectedLevel) => {
|
|
339
|
+
jest.spyOn(Horizon.Server.prototype, 'feeStats').mockResolvedValue({
|
|
337
340
|
ledger_capacity_usage: usage,
|
|
338
|
-
fee_charged: { mode:
|
|
339
|
-
} as Awaited<ReturnType<Horizon.Server[
|
|
340
|
-
|
|
341
|
-
const fees = await fetchBaseFee()
|
|
342
|
-
expect(fees.networkCongestionLevel).toBe(expectedLevel)
|
|
343
|
-
expect(fees.recommendedFee).toBe(200)
|
|
344
|
-
})
|
|
345
|
-
|
|
346
|
-
it(
|
|
347
|
-
jest
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
it("returns height hash and time from latest ledger record", async () => {
|
|
359
|
-
jest.spyOn(Horizon.Server.prototype, "ledgers").mockReturnValue({
|
|
341
|
+
fee_charged: { mode: '200' },
|
|
342
|
+
} as Awaited<ReturnType<Horizon.Server['feeStats']>>)
|
|
343
|
+
|
|
344
|
+
const fees = await fetchBaseFee()
|
|
345
|
+
expect(fees.networkCongestionLevel).toBe(expectedLevel)
|
|
346
|
+
expect(fees.recommendedFee).toBe(200)
|
|
347
|
+
})
|
|
348
|
+
|
|
349
|
+
it('falls back to defaults when feeStats throws', async () => {
|
|
350
|
+
jest.spyOn(Horizon.Server.prototype, 'feeStats').mockRejectedValue(new Error('network error'))
|
|
351
|
+
|
|
352
|
+
const fees = await fetchBaseFee()
|
|
353
|
+
expect(fees.baseFee).toBeGreaterThan(0)
|
|
354
|
+
expect(fees.networkCongestionLevel).toBe(NetworkCongestionLevel.MEDIUM)
|
|
355
|
+
})
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
describe('getLastBlock', () => {
|
|
359
|
+
it('returns height hash and time from latest ledger record', async () => {
|
|
360
|
+
jest.spyOn(Horizon.Server.prototype, 'ledgers').mockReturnValue({
|
|
360
361
|
order: jest.fn().mockReturnThis(),
|
|
361
362
|
limit: jest.fn().mockReturnValue({
|
|
362
363
|
call: jest.fn().mockResolvedValue({
|
|
363
|
-
records: [{ sequence: 42, hash:
|
|
364
|
+
records: [{ sequence: 42, hash: 'ab'.repeat(32), closed_at: '2018-09-15T15:40:05Z' }],
|
|
364
365
|
}),
|
|
365
366
|
}),
|
|
366
|
-
} as unknown as ReturnType<Horizon.Server[
|
|
367
|
+
} as unknown as ReturnType<Horizon.Server['ledgers']>)
|
|
367
368
|
|
|
368
|
-
const block = await getLastBlock()
|
|
369
|
-
expect(block.height).toBe(42)
|
|
370
|
-
expect(block.hash).toBe(
|
|
371
|
-
expect(block.time).toEqual(new Date(
|
|
372
|
-
})
|
|
373
|
-
})
|
|
369
|
+
const block = await getLastBlock()
|
|
370
|
+
expect(block.height).toBe(42)
|
|
371
|
+
expect(block.hash).toBe('ab'.repeat(32))
|
|
372
|
+
expect(block.time).toEqual(new Date('2018-09-15T15:40:05Z'))
|
|
373
|
+
})
|
|
374
|
+
})
|
|
374
375
|
|
|
375
|
-
describe(
|
|
376
|
-
let submitTransactionSpy: jest.SpiedFunction<Horizon.Server[
|
|
376
|
+
describe('broadcastTransaction decode / documentation edge cases', () => {
|
|
377
|
+
let submitTransactionSpy: jest.SpiedFunction<Horizon.Server['submitTransaction']>
|
|
377
378
|
|
|
378
379
|
beforeEach(() => {
|
|
379
380
|
submitTransactionSpy = jest
|
|
380
|
-
.spyOn(Horizon.Server.prototype,
|
|
381
|
-
.mockRejectedValue(new Error(
|
|
382
|
-
})
|
|
381
|
+
.spyOn(Horizon.Server.prototype, 'submitTransaction')
|
|
382
|
+
.mockRejectedValue(new Error('mock not configured'))
|
|
383
|
+
})
|
|
383
384
|
|
|
384
|
-
it(
|
|
385
|
+
it('uses Unknown transaction result code when Horizon code is not in the map', async () => {
|
|
385
386
|
const body = {
|
|
386
|
-
type:
|
|
387
|
-
title:
|
|
387
|
+
type: 'https://stellar.org/horizon-errors/transaction_failed',
|
|
388
|
+
title: 'Transaction Failed',
|
|
388
389
|
status: 400,
|
|
389
|
-
detail:
|
|
390
|
+
detail: 'failed',
|
|
390
391
|
extras: {
|
|
391
|
-
result_codes: { transaction:
|
|
392
|
-
result_xdr:
|
|
392
|
+
result_codes: { transaction: 'tx_completely_unknown', operations: [] as string[] },
|
|
393
|
+
result_xdr: 'AAAAAAAAAGT////4AAAAAA==',
|
|
393
394
|
envelope_xdr: signedTxFixture,
|
|
394
395
|
},
|
|
395
|
-
}
|
|
396
|
+
}
|
|
396
397
|
submitTransactionSpy.mockRejectedValue(
|
|
397
398
|
new BadResponseError(
|
|
398
|
-
|
|
399
|
-
body
|
|
400
|
-
)
|
|
401
|
-
)
|
|
399
|
+
'Transaction submission failed. Server responded: 400 Bad Request',
|
|
400
|
+
body
|
|
401
|
+
)
|
|
402
|
+
)
|
|
402
403
|
|
|
403
404
|
await expect(broadcastTransaction(signedTxFixture)).rejects.toMatchObject({
|
|
404
|
-
name:
|
|
405
|
-
documentationSummary:
|
|
406
|
-
})
|
|
407
|
-
})
|
|
405
|
+
name: 'StellarBroadcastFailedError',
|
|
406
|
+
documentationSummary: 'Unknown transaction result code.',
|
|
407
|
+
})
|
|
408
|
+
})
|
|
408
409
|
|
|
409
|
-
it(
|
|
410
|
+
it('marks decodeFailed when result_xdr cannot be decoded', async () => {
|
|
410
411
|
const body = {
|
|
411
|
-
type:
|
|
412
|
-
title:
|
|
412
|
+
type: 'https://stellar.org/horizon-errors/transaction_failed',
|
|
413
|
+
title: 'Transaction Failed',
|
|
413
414
|
status: 400,
|
|
414
|
-
detail:
|
|
415
|
+
detail: 'failed',
|
|
415
416
|
extras: {
|
|
416
|
-
result_codes: { transaction:
|
|
417
|
-
result_xdr:
|
|
417
|
+
result_codes: { transaction: 'tx_failed', operations: [] as string[] },
|
|
418
|
+
result_xdr: 'not-valid-base64!!!',
|
|
418
419
|
envelope_xdr: signedTxFixture,
|
|
419
420
|
},
|
|
420
|
-
}
|
|
421
|
+
}
|
|
421
422
|
submitTransactionSpy.mockRejectedValue(
|
|
422
423
|
new BadResponseError(
|
|
423
|
-
|
|
424
|
-
body
|
|
425
|
-
)
|
|
426
|
-
)
|
|
424
|
+
'Transaction submission failed. Server responded: 400 Bad Request',
|
|
425
|
+
body
|
|
426
|
+
)
|
|
427
|
+
)
|
|
427
428
|
|
|
428
429
|
await expect(broadcastTransaction(signedTxFixture)).rejects.toMatchObject({
|
|
429
|
-
name:
|
|
430
|
+
name: 'StellarBroadcastFailedError',
|
|
430
431
|
decodedResultXdr: { decodeFailed: true },
|
|
431
|
-
})
|
|
432
|
-
})
|
|
433
|
-
})
|
|
434
|
-
})
|
|
432
|
+
})
|
|
433
|
+
})
|
|
434
|
+
})
|
|
435
|
+
})
|