hive-stream 3.0.2 → 3.0.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/DOCUMENTATION.md +50 -2
- package/README.md +282 -4
- package/dist/adapters/base.adapter.d.ts +5 -0
- package/dist/adapters/base.adapter.js +9 -0
- package/dist/adapters/base.adapter.js.map +1 -1
- package/dist/adapters/mongodb.adapter.d.ts +6 -6
- package/dist/adapters/mongodb.adapter.js +36 -21
- package/dist/adapters/mongodb.adapter.js.map +1 -1
- package/dist/adapters/postgresql.adapter.d.ts +7 -0
- package/dist/adapters/postgresql.adapter.js +46 -19
- package/dist/adapters/postgresql.adapter.js.map +1 -1
- package/dist/adapters/sqlite.adapter.d.ts +4 -0
- package/dist/adapters/sqlite.adapter.js +10 -0
- package/dist/adapters/sqlite.adapter.js.map +1 -1
- package/dist/api.d.ts +13 -3
- package/dist/api.js +96 -62
- package/dist/api.js.map +1 -1
- package/dist/builders.d.ts +176 -0
- package/dist/builders.js +727 -0
- package/dist/builders.js.map +1 -0
- package/dist/config.d.ts +16 -1
- package/dist/config.js +95 -3
- package/dist/config.js.map +1 -1
- package/dist/contracts/auctionhouse.contract.d.ts +4 -0
- package/dist/contracts/auctionhouse.contract.js +234 -0
- package/dist/contracts/auctionhouse.contract.js.map +1 -0
- package/dist/contracts/booking.contract.d.ts +4 -0
- package/dist/contracts/booking.contract.js +225 -0
- package/dist/contracts/booking.contract.js.map +1 -0
- package/dist/contracts/bountyboard.contract.d.ts +4 -0
- package/dist/contracts/bountyboard.contract.js +233 -0
- package/dist/contracts/bountyboard.contract.js.map +1 -0
- package/dist/contracts/bundlemarketplace.contract.d.ts +4 -0
- package/dist/contracts/bundlemarketplace.contract.js +195 -0
- package/dist/contracts/bundlemarketplace.contract.js.map +1 -0
- package/dist/contracts/charitymatch.contract.d.ts +4 -0
- package/dist/contracts/charitymatch.contract.js +172 -0
- package/dist/contracts/charitymatch.contract.js.map +1 -0
- package/dist/contracts/coinflip.contract.js +25 -22
- package/dist/contracts/coinflip.contract.js.map +1 -1
- package/dist/contracts/crowdfund.contract.d.ts +4 -0
- package/dist/contracts/crowdfund.contract.js +290 -0
- package/dist/contracts/crowdfund.contract.js.map +1 -0
- package/dist/contracts/dcabot.contract.d.ts +4 -0
- package/dist/contracts/dcabot.contract.js +217 -0
- package/dist/contracts/dcabot.contract.js.map +1 -0
- package/dist/contracts/dice.contract.js +25 -22
- package/dist/contracts/dice.contract.js.map +1 -1
- package/dist/contracts/domainregistry.contract.d.ts +4 -0
- package/dist/contracts/domainregistry.contract.js +232 -0
- package/dist/contracts/domainregistry.contract.js.map +1 -0
- package/dist/contracts/exchange.contract.js +209 -168
- package/dist/contracts/exchange.contract.js.map +1 -1
- package/dist/contracts/fanclub.contract.d.ts +4 -0
- package/dist/contracts/fanclub.contract.js +193 -0
- package/dist/contracts/fanclub.contract.js.map +1 -0
- package/dist/contracts/giftcard.contract.d.ts +4 -0
- package/dist/contracts/giftcard.contract.js +158 -0
- package/dist/contracts/giftcard.contract.js.map +1 -0
- package/dist/contracts/grantrounds.contract.d.ts +4 -0
- package/dist/contracts/grantrounds.contract.js +265 -0
- package/dist/contracts/grantrounds.contract.js.map +1 -0
- package/dist/contracts/groupbuy.contract.d.ts +4 -0
- package/dist/contracts/groupbuy.contract.js +198 -0
- package/dist/contracts/groupbuy.contract.js.map +1 -0
- package/dist/contracts/helpers.d.ts +66 -0
- package/dist/contracts/helpers.js +166 -0
- package/dist/contracts/helpers.js.map +1 -0
- package/dist/contracts/insurancepool.contract.d.ts +4 -0
- package/dist/contracts/insurancepool.contract.js +281 -0
- package/dist/contracts/insurancepool.contract.js.map +1 -0
- package/dist/contracts/invoice.contract.d.ts +4 -0
- package/dist/contracts/invoice.contract.js +193 -0
- package/dist/contracts/invoice.contract.js.map +1 -0
- package/dist/contracts/launchpad.contract.d.ts +4 -0
- package/dist/contracts/launchpad.contract.js +225 -0
- package/dist/contracts/launchpad.contract.js.map +1 -0
- package/dist/contracts/lotto.contract.js +53 -37
- package/dist/contracts/lotto.contract.js.map +1 -1
- package/dist/contracts/multisigtreasury.contract.d.ts +4 -0
- package/dist/contracts/multisigtreasury.contract.js +245 -0
- package/dist/contracts/multisigtreasury.contract.js.map +1 -0
- package/dist/contracts/nft.contract.d.ts +1 -0
- package/dist/contracts/nft.contract.js +234 -195
- package/dist/contracts/nft.contract.js.map +1 -1
- package/dist/contracts/oraclebounty.contract.d.ts +4 -0
- package/dist/contracts/oraclebounty.contract.js +250 -0
- package/dist/contracts/oraclebounty.contract.js.map +1 -0
- package/dist/contracts/payroll.contract.d.ts +4 -0
- package/dist/contracts/payroll.contract.js +232 -0
- package/dist/contracts/payroll.contract.js.map +1 -0
- package/dist/contracts/paywall.contract.d.ts +4 -0
- package/dist/contracts/paywall.contract.js +185 -0
- package/dist/contracts/paywall.contract.js.map +1 -0
- package/dist/contracts/poll.contract.js +2 -0
- package/dist/contracts/poll.contract.js.map +1 -1
- package/dist/contracts/predictionmarket.contract.d.ts +4 -0
- package/dist/contracts/predictionmarket.contract.js +213 -0
- package/dist/contracts/predictionmarket.contract.js.map +1 -0
- package/dist/contracts/proposaltimelock.contract.d.ts +4 -0
- package/dist/contracts/proposaltimelock.contract.js +250 -0
- package/dist/contracts/proposaltimelock.contract.js.map +1 -0
- package/dist/contracts/questpass.contract.d.ts +4 -0
- package/dist/contracts/questpass.contract.js +214 -0
- package/dist/contracts/questpass.contract.js.map +1 -0
- package/dist/contracts/referral.contract.d.ts +4 -0
- package/dist/contracts/referral.contract.js +238 -0
- package/dist/contracts/referral.contract.js.map +1 -0
- package/dist/contracts/rental.contract.d.ts +4 -0
- package/dist/contracts/rental.contract.js +221 -0
- package/dist/contracts/rental.contract.js.map +1 -0
- package/dist/contracts/revenuesplit.contract.d.ts +4 -0
- package/dist/contracts/revenuesplit.contract.js +211 -0
- package/dist/contracts/revenuesplit.contract.js.map +1 -0
- package/dist/contracts/rps.contract.js +48 -20
- package/dist/contracts/rps.contract.js.map +1 -1
- package/dist/contracts/savings.contract.d.ts +4 -0
- package/dist/contracts/savings.contract.js +208 -0
- package/dist/contracts/savings.contract.js.map +1 -0
- package/dist/contracts/subscription.contract.d.ts +4 -0
- package/dist/contracts/subscription.contract.js +241 -0
- package/dist/contracts/subscription.contract.js.map +1 -0
- package/dist/contracts/sweepstakes.contract.d.ts +4 -0
- package/dist/contracts/sweepstakes.contract.js +209 -0
- package/dist/contracts/sweepstakes.contract.js.map +1 -0
- package/dist/contracts/ticketing.contract.d.ts +4 -0
- package/dist/contracts/ticketing.contract.js +185 -0
- package/dist/contracts/ticketing.contract.js.map +1 -0
- package/dist/contracts/tipjar.contract.js +2 -0
- package/dist/contracts/tipjar.contract.js.map +1 -1
- package/dist/contracts/token.contract.js +135 -125
- package/dist/contracts/token.contract.js.map +1 -1
- package/dist/index.d.ts +40 -0
- package/dist/index.js +72 -1
- package/dist/index.js.map +1 -1
- package/dist/metadata.d.ts +20 -0
- package/dist/metadata.js +320 -1
- package/dist/metadata.js.map +1 -1
- package/dist/providers/block-provider.d.ts +22 -0
- package/dist/providers/block-provider.js +3 -0
- package/dist/providers/block-provider.js.map +1 -0
- package/dist/providers/haf-client.d.ts +30 -0
- package/dist/providers/haf-client.js +119 -0
- package/dist/providers/haf-client.js.map +1 -0
- package/dist/providers/haf-provider.d.ts +49 -0
- package/dist/providers/haf-provider.js +256 -0
- package/dist/providers/haf-provider.js.map +1 -0
- package/dist/providers/hive-provider.d.ts +13 -0
- package/dist/providers/hive-provider.js +25 -0
- package/dist/providers/hive-provider.js.map +1 -0
- package/dist/providers/index.d.ts +4 -0
- package/dist/providers/index.js +21 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/streamer.d.ts +65 -4
- package/dist/streamer.js +768 -72
- package/dist/streamer.js.map +1 -1
- package/dist/types/hive-stream.d.ts +317 -0
- package/dist/utils.d.ts +33 -0
- package/dist/utils.js +198 -2
- package/dist/utils.js.map +1 -1
- package/package.json +16 -1
- package/.claude/settings.local.json +0 -12
- package/.env.example +0 -3
- package/.travis.yml +0 -11
- package/AGENTS.md +0 -35
- package/CLAUDE.md +0 -75
- package/ecosystem.config.js +0 -17
- package/examples/contracts/README.md +0 -8
- package/examples/contracts/exchange.ts +0 -38
- package/examples/contracts/poll.ts +0 -21
- package/examples/contracts/rps.ts +0 -19
- package/examples/contracts/tipjar.ts +0 -19
- package/jest.config.js +0 -9
- package/test-contract-block.md +0 -19
- package/tests/actions.spec.ts +0 -252
- package/tests/adapters/actions-persistence.spec.ts +0 -144
- package/tests/adapters/postgresql.adapter.spec.ts +0 -127
- package/tests/adapters/sqlite.adapter.spec.ts +0 -181
- package/tests/config-input.spec.ts +0 -90
- package/tests/contracts/coinflip.contract.spec.ts +0 -94
- package/tests/contracts/dice.contract.spec.ts +0 -87
- package/tests/contracts/entrants.json +0 -729
- package/tests/contracts/exchange.contract.spec.ts +0 -84
- package/tests/contracts/lotto.contract.spec.ts +0 -59
- package/tests/contracts/nft.contract.spec.ts +0 -948
- package/tests/contracts/token.contract.spec.ts +0 -90
- package/tests/exchanges/coingecko.exchange.spec.ts +0 -169
- package/tests/exchanges/exchange.base.spec.ts +0 -246
- package/tests/helpers/mock-adapter.ts +0 -214
- package/tests/helpers/mock-fetch.ts +0 -165
- package/tests/hive-chain-features.spec.ts +0 -319
- package/tests/hive-rates.spec.ts +0 -443
- package/tests/integration/hive-rates.integration.spec.ts +0 -35
- package/tests/metadata.spec.ts +0 -63
- package/tests/setup.ts +0 -30
- package/tests/streamer-actions.spec.ts +0 -274
- package/tests/streamer.spec.ts +0 -342
- package/tests/types/rates.spec.ts +0 -216
- package/tests/utils.spec.ts +0 -113
- package/tsconfig.build.json +0 -4
- package/tslint.json +0 -21
- package/wallaby.js +0 -26
package/tests/hive-rates.spec.ts
DELETED
|
@@ -1,443 +0,0 @@
|
|
|
1
|
-
import { HiveRates } from '../src/hive-rates';
|
|
2
|
-
import { CoinGeckoExchange } from '../src/exchanges/coingecko';
|
|
3
|
-
import { Exchange } from '../src/exchanges/exchange';
|
|
4
|
-
import { NetworkError, ValidationError, RatesError } from '../src/types/rates';
|
|
5
|
-
|
|
6
|
-
// Mock fetch for tests
|
|
7
|
-
const mockFetch = jest.fn() as jest.MockedFunction<typeof fetch>;
|
|
8
|
-
global.fetch = mockFetch;
|
|
9
|
-
|
|
10
|
-
class MockExchange extends Exchange {
|
|
11
|
-
public readonly exchangeId = 'mock-exchange';
|
|
12
|
-
public shouldSucceed = true;
|
|
13
|
-
public mockHiveRate = 0.5;
|
|
14
|
-
public mockHbdRate = 1.0;
|
|
15
|
-
|
|
16
|
-
constructor(config: Partial<{ cacheDuration: number; maxRetries: number; retryDelay: number }> = {}) {
|
|
17
|
-
// Use shorter timeouts for tests
|
|
18
|
-
super({
|
|
19
|
-
cacheDuration: config.cacheDuration ?? 100,
|
|
20
|
-
maxRetries: config.maxRetries ?? 1,
|
|
21
|
-
retryDelay: config.retryDelay ?? 10
|
|
22
|
-
});
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
public async fetchRates(): Promise<boolean> {
|
|
26
|
-
if (!this.shouldSucceed) {
|
|
27
|
-
throw new Error('Mock exchange error');
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
this.rateUsdHive = this.mockHiveRate;
|
|
31
|
-
this.rateUsdHbd = this.mockHbdRate;
|
|
32
|
-
return true;
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
describe('HiveRates', () => {
|
|
37
|
-
let hiveRates: HiveRates;
|
|
38
|
-
let mockExchange: MockExchange;
|
|
39
|
-
|
|
40
|
-
beforeEach(() => {
|
|
41
|
-
mockExchange = new MockExchange({ cacheDuration: 100 });
|
|
42
|
-
hiveRates = new HiveRates({ cacheDuration: 100 }, [mockExchange]);
|
|
43
|
-
mockFetch.mockClear();
|
|
44
|
-
jest.clearAllTimers();
|
|
45
|
-
jest.useFakeTimers();
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
afterEach(() => {
|
|
49
|
-
jest.useRealTimers();
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
describe('constructor', () => {
|
|
53
|
-
it('should use default CoinGecko exchange when no custom exchanges provided', () => {
|
|
54
|
-
const rates = new HiveRates();
|
|
55
|
-
expect(rates).toBeDefined();
|
|
56
|
-
});
|
|
57
|
-
|
|
58
|
-
it('should use custom exchanges when provided', () => {
|
|
59
|
-
const customExchange = new MockExchange();
|
|
60
|
-
const rates = new HiveRates({}, [customExchange]);
|
|
61
|
-
expect(rates).toBeDefined();
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it('should use default config when none provided', () => {
|
|
65
|
-
const rates = new HiveRates();
|
|
66
|
-
expect(rates).toBeDefined();
|
|
67
|
-
});
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
describe('fetchRates', () => {
|
|
71
|
-
beforeEach(() => {
|
|
72
|
-
// Mock successful fiat API response
|
|
73
|
-
mockFetch.mockResolvedValue({
|
|
74
|
-
ok: true,
|
|
75
|
-
json: async () => ({
|
|
76
|
-
usd: {
|
|
77
|
-
eur: 0.85,
|
|
78
|
-
gbp: 0.73,
|
|
79
|
-
jpy: 110,
|
|
80
|
-
cad: 1.25,
|
|
81
|
-
aud: 1.35
|
|
82
|
-
}
|
|
83
|
-
}),
|
|
84
|
-
} as Response);
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('should fetch rates successfully', async () => {
|
|
88
|
-
const result = await hiveRates.fetchRates();
|
|
89
|
-
|
|
90
|
-
expect(result).toBe(true);
|
|
91
|
-
|
|
92
|
-
// Check crypto rates
|
|
93
|
-
const cryptoRates = hiveRates.getCryptoRates();
|
|
94
|
-
expect(cryptoRates.hive).toBe(0.5);
|
|
95
|
-
expect(cryptoRates.hbd).toBe(1.0);
|
|
96
|
-
|
|
97
|
-
// Check some cross rates
|
|
98
|
-
expect(hiveRates.getRate('EUR', 'HIVE')).toBeCloseTo(0.5 * 0.85);
|
|
99
|
-
expect(hiveRates.getRate('GBP', 'HBD')).toBeCloseTo(1.0 * 0.73);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it('should handle crypto fetch failure gracefully', async () => {
|
|
103
|
-
mockExchange.shouldSucceed = false;
|
|
104
|
-
|
|
105
|
-
const result = await hiveRates.fetchRates();
|
|
106
|
-
|
|
107
|
-
// Should still succeed if fiat rates succeed
|
|
108
|
-
expect(result).toBe(true);
|
|
109
|
-
}, 10000);
|
|
110
|
-
|
|
111
|
-
it('should handle fiat fetch failure gracefully', async () => {
|
|
112
|
-
mockFetch.mockRejectedValue(new Error('Fiat API error'));
|
|
113
|
-
|
|
114
|
-
// Should still succeed if crypto rates succeed
|
|
115
|
-
const result = await hiveRates.fetchRates();
|
|
116
|
-
expect(result).toBe(true);
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
it('should return false when both crypto and fiat fail', async () => {
|
|
120
|
-
mockExchange.shouldSucceed = false;
|
|
121
|
-
mockFetch.mockRejectedValue(new Error('All APIs failed'));
|
|
122
|
-
|
|
123
|
-
const result = await hiveRates.fetchRates();
|
|
124
|
-
expect(result).toBe(false);
|
|
125
|
-
}, 10000);
|
|
126
|
-
|
|
127
|
-
it('should calculate average rates from multiple exchanges', async () => {
|
|
128
|
-
const exchange1 = new MockExchange();
|
|
129
|
-
exchange1.mockHiveRate = 0.4;
|
|
130
|
-
exchange1.mockHbdRate = 0.9;
|
|
131
|
-
|
|
132
|
-
const exchange2 = new MockExchange();
|
|
133
|
-
exchange2.mockHiveRate = 0.6;
|
|
134
|
-
exchange2.mockHbdRate = 1.1;
|
|
135
|
-
|
|
136
|
-
const rates = new HiveRates({ cacheDuration: 100 }, [exchange1, exchange2]);
|
|
137
|
-
|
|
138
|
-
await rates.fetchRates();
|
|
139
|
-
|
|
140
|
-
const cryptoRates = rates.getCryptoRates();
|
|
141
|
-
expect(cryptoRates.hive).toBe(0.5); // Average of 0.4 and 0.6
|
|
142
|
-
expect(cryptoRates.hbd).toBe(1.0); // Average of 0.9 and 1.1
|
|
143
|
-
});
|
|
144
|
-
|
|
145
|
-
it('should ignore invalid crypto rates in average calculation', async () => {
|
|
146
|
-
const exchange1 = new MockExchange();
|
|
147
|
-
exchange1.mockHiveRate = 0.5;
|
|
148
|
-
exchange1.mockHbdRate = 1.0;
|
|
149
|
-
|
|
150
|
-
const exchange2 = new MockExchange();
|
|
151
|
-
exchange2.mockHiveRate = 0; // Invalid
|
|
152
|
-
exchange2.mockHbdRate = -1; // Invalid
|
|
153
|
-
|
|
154
|
-
const rates = new HiveRates({ cacheDuration: 100 }, [exchange1, exchange2]);
|
|
155
|
-
|
|
156
|
-
await rates.fetchRates();
|
|
157
|
-
|
|
158
|
-
const cryptoRates = rates.getCryptoRates();
|
|
159
|
-
expect(cryptoRates.hive).toBe(0.5); // Only valid rate used
|
|
160
|
-
expect(cryptoRates.hbd).toBe(1.0); // Only valid rate used
|
|
161
|
-
});
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
describe('rate retrieval methods', () => {
|
|
165
|
-
beforeEach(async () => {
|
|
166
|
-
mockFetch.mockResolvedValue({
|
|
167
|
-
ok: true,
|
|
168
|
-
json: async () => ({
|
|
169
|
-
usd: {
|
|
170
|
-
eur: 0.85,
|
|
171
|
-
gbp: 0.73,
|
|
172
|
-
jpy: 110
|
|
173
|
-
}
|
|
174
|
-
}),
|
|
175
|
-
} as Response);
|
|
176
|
-
|
|
177
|
-
await hiveRates.fetchRates();
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it('should get specific rate correctly', () => {
|
|
181
|
-
const rate = hiveRates.getRate('EUR', 'HIVE');
|
|
182
|
-
expect(rate).toBeCloseTo(0.5 * 0.85);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it('should return null for non-existent rate', () => {
|
|
186
|
-
const rate = hiveRates.getRate('XYZ' as any, 'HIVE');
|
|
187
|
-
expect(rate).toBeNull();
|
|
188
|
-
});
|
|
189
|
-
|
|
190
|
-
it('should get all rates', () => {
|
|
191
|
-
const allRates = hiveRates.getAllRates();
|
|
192
|
-
expect(typeof allRates).toBe('object');
|
|
193
|
-
expect(allRates['EUR_HIVE']).toBeCloseTo(0.5 * 0.85);
|
|
194
|
-
expect(allRates['GBP_HBD']).toBeCloseTo(1.0 * 0.73);
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
it('should get crypto rates only', () => {
|
|
198
|
-
const cryptoRates = hiveRates.getCryptoRates();
|
|
199
|
-
expect(cryptoRates.hive).toBe(0.5);
|
|
200
|
-
expect(cryptoRates.hbd).toBe(1.0);
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
it('should get fiat rates only', () => {
|
|
204
|
-
const fiatRates = hiveRates.getFiatRates();
|
|
205
|
-
expect(fiatRates.EUR).toBe(0.85);
|
|
206
|
-
expect(fiatRates.GBP).toBe(0.73);
|
|
207
|
-
expect(fiatRates.JPY).toBe(110);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
it('should support legacy method', () => {
|
|
211
|
-
const rate = hiveRates.fiatToHiveRate('EUR', 'HIVE');
|
|
212
|
-
expect(rate).toBeCloseTo(0.5 * 0.85);
|
|
213
|
-
});
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
describe('caching behavior', () => {
|
|
217
|
-
beforeEach(() => {
|
|
218
|
-
mockFetch.mockResolvedValue({
|
|
219
|
-
ok: true,
|
|
220
|
-
json: async () => ({
|
|
221
|
-
usd: { eur: 0.85 }
|
|
222
|
-
}),
|
|
223
|
-
} as Response);
|
|
224
|
-
});
|
|
225
|
-
|
|
226
|
-
it('should respect cache duration', async () => {
|
|
227
|
-
// First fetch
|
|
228
|
-
await hiveRates.fetchRates();
|
|
229
|
-
|
|
230
|
-
// Second fetch within cache duration should not call API
|
|
231
|
-
mockFetch.mockClear();
|
|
232
|
-
await hiveRates.fetchRates();
|
|
233
|
-
|
|
234
|
-
expect(mockFetch).not.toHaveBeenCalled();
|
|
235
|
-
});
|
|
236
|
-
|
|
237
|
-
it('should fetch when cache expires', async () => {
|
|
238
|
-
// First fetch
|
|
239
|
-
await hiveRates.fetchRates();
|
|
240
|
-
|
|
241
|
-
// Advance time beyond cache duration
|
|
242
|
-
jest.advanceTimersByTime(150);
|
|
243
|
-
|
|
244
|
-
// Second fetch should call API
|
|
245
|
-
mockFetch.mockClear();
|
|
246
|
-
await hiveRates.fetchRates();
|
|
247
|
-
|
|
248
|
-
expect(mockFetch).toHaveBeenCalled();
|
|
249
|
-
});
|
|
250
|
-
|
|
251
|
-
it('should track last fetch times', async () => {
|
|
252
|
-
const timesBefore = hiveRates.getLastFetchTimes();
|
|
253
|
-
expect(timesBefore.crypto).toBeUndefined();
|
|
254
|
-
expect(timesBefore.fiat).toBeUndefined();
|
|
255
|
-
|
|
256
|
-
await hiveRates.fetchRates();
|
|
257
|
-
|
|
258
|
-
const timesAfter = hiveRates.getLastFetchTimes();
|
|
259
|
-
expect(timesAfter.crypto).toBeDefined();
|
|
260
|
-
expect(timesAfter.fiat).toBeDefined();
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
it('should report cache validity', async () => {
|
|
264
|
-
const validityBefore = hiveRates.isCacheValid();
|
|
265
|
-
expect(validityBefore.crypto).toBe(false);
|
|
266
|
-
expect(validityBefore.fiat).toBe(false);
|
|
267
|
-
|
|
268
|
-
await hiveRates.fetchRates();
|
|
269
|
-
|
|
270
|
-
const validityAfter = hiveRates.isCacheValid();
|
|
271
|
-
expect(validityAfter.crypto).toBe(true);
|
|
272
|
-
expect(validityAfter.fiat).toBe(true);
|
|
273
|
-
|
|
274
|
-
jest.advanceTimersByTime(150);
|
|
275
|
-
|
|
276
|
-
const validityExpired = hiveRates.isCacheValid();
|
|
277
|
-
expect(validityExpired.crypto).toBe(false);
|
|
278
|
-
expect(validityExpired.fiat).toBe(false);
|
|
279
|
-
});
|
|
280
|
-
});
|
|
281
|
-
|
|
282
|
-
describe('fiat API handling', () => {
|
|
283
|
-
it('should try multiple fiat endpoints', async () => {
|
|
284
|
-
// First endpoint fails, second succeeds
|
|
285
|
-
mockFetch
|
|
286
|
-
.mockRejectedValueOnce(new Error('First endpoint failed'))
|
|
287
|
-
.mockResolvedValueOnce({
|
|
288
|
-
ok: true,
|
|
289
|
-
json: async () => ({
|
|
290
|
-
usd: { eur: 0.85 }
|
|
291
|
-
}),
|
|
292
|
-
} as Response);
|
|
293
|
-
|
|
294
|
-
const result = await hiveRates.fetchRates();
|
|
295
|
-
expect(result).toBe(true);
|
|
296
|
-
expect(mockFetch).toHaveBeenCalledTimes(2);
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
it('should handle all fiat endpoints failing', async () => {
|
|
300
|
-
mockFetch.mockRejectedValue(new Error('All endpoints failed'));
|
|
301
|
-
|
|
302
|
-
// This should still succeed because crypto fetch succeeds
|
|
303
|
-
const result = await hiveRates.fetchRates();
|
|
304
|
-
expect(result).toBe(true);
|
|
305
|
-
});
|
|
306
|
-
|
|
307
|
-
it('should validate fiat response format', async () => {
|
|
308
|
-
mockFetch.mockResolvedValue({
|
|
309
|
-
ok: true,
|
|
310
|
-
json: async () => ({ invalid: 'format' }),
|
|
311
|
-
} as Response);
|
|
312
|
-
|
|
313
|
-
// Should still succeed because crypto fetch succeeds, fiat just fails silently
|
|
314
|
-
const result = await hiveRates.fetchRates();
|
|
315
|
-
expect(result).toBe(true);
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
it('should filter invalid fiat rates', async () => {
|
|
319
|
-
mockFetch.mockResolvedValue({
|
|
320
|
-
ok: true,
|
|
321
|
-
json: async () => ({
|
|
322
|
-
usd: {
|
|
323
|
-
eur: 0.85,
|
|
324
|
-
invalid: 'string',
|
|
325
|
-
nan: NaN,
|
|
326
|
-
negative: -1,
|
|
327
|
-
zero: 0
|
|
328
|
-
}
|
|
329
|
-
}),
|
|
330
|
-
} as Response);
|
|
331
|
-
|
|
332
|
-
await hiveRates.fetchRates();
|
|
333
|
-
|
|
334
|
-
const fiatRates = hiveRates.getFiatRates();
|
|
335
|
-
expect(fiatRates.EUR).toBe(0.85);
|
|
336
|
-
expect(fiatRates.INVALID).toBeUndefined();
|
|
337
|
-
expect(fiatRates.NAN).toBeUndefined();
|
|
338
|
-
expect(fiatRates.NEGATIVE).toBeUndefined();
|
|
339
|
-
expect(fiatRates.ZERO).toBeUndefined();
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
it('should convert currency codes to uppercase', async () => {
|
|
343
|
-
mockFetch.mockResolvedValue({
|
|
344
|
-
ok: true,
|
|
345
|
-
json: async () => ({
|
|
346
|
-
usd: {
|
|
347
|
-
eur: 0.85,
|
|
348
|
-
gbp: 0.73
|
|
349
|
-
}
|
|
350
|
-
}),
|
|
351
|
-
} as Response);
|
|
352
|
-
|
|
353
|
-
await hiveRates.fetchRates();
|
|
354
|
-
|
|
355
|
-
const fiatRates = hiveRates.getFiatRates();
|
|
356
|
-
expect(fiatRates.EUR).toBe(0.85);
|
|
357
|
-
expect(fiatRates.GBP).toBe(0.73);
|
|
358
|
-
});
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
describe('error handling', () => {
|
|
362
|
-
it('should throw RatesError for unexpected errors', async () => {
|
|
363
|
-
// Mock an unexpected error in fetchCryptoRates
|
|
364
|
-
const originalMethod = hiveRates['fetchCryptoRates'];
|
|
365
|
-
hiveRates['fetchCryptoRates'] = jest.fn().mockImplementation(() => {
|
|
366
|
-
throw new TypeError('Unexpected error');
|
|
367
|
-
});
|
|
368
|
-
|
|
369
|
-
await expect(hiveRates.fetchRates()).rejects.toThrow(RatesError);
|
|
370
|
-
await expect(hiveRates.fetchRates()).rejects.toThrow('Unexpected error');
|
|
371
|
-
|
|
372
|
-
// Restore original method
|
|
373
|
-
hiveRates['fetchCryptoRates'] = originalMethod;
|
|
374
|
-
});
|
|
375
|
-
|
|
376
|
-
it('should preserve known error types', async () => {
|
|
377
|
-
mockFetch.mockResolvedValue({
|
|
378
|
-
ok: true,
|
|
379
|
-
json: async () => ({ invalid: 'format' }),
|
|
380
|
-
} as Response);
|
|
381
|
-
|
|
382
|
-
// Should still succeed because crypto fetch succeeds, fiat just fails silently
|
|
383
|
-
const result = await hiveRates.fetchRates();
|
|
384
|
-
expect(result).toBe(true);
|
|
385
|
-
});
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
describe('edge cases', () => {
|
|
389
|
-
it('should handle empty fiat rates response', async () => {
|
|
390
|
-
mockFetch.mockResolvedValue({
|
|
391
|
-
ok: true,
|
|
392
|
-
json: async () => ({
|
|
393
|
-
usd: {}
|
|
394
|
-
}),
|
|
395
|
-
} as Response);
|
|
396
|
-
|
|
397
|
-
// Should still succeed because crypto fetch succeeds, fiat just fails silently
|
|
398
|
-
const result = await hiveRates.fetchRates();
|
|
399
|
-
expect(result).toBe(true);
|
|
400
|
-
});
|
|
401
|
-
|
|
402
|
-
it('should handle no valid crypto rates', async () => {
|
|
403
|
-
mockExchange.mockHiveRate = 0;
|
|
404
|
-
mockExchange.mockHbdRate = 0;
|
|
405
|
-
|
|
406
|
-
mockFetch.mockResolvedValue({
|
|
407
|
-
ok: true,
|
|
408
|
-
json: async () => ({
|
|
409
|
-
usd: { eur: 0.85 }
|
|
410
|
-
}),
|
|
411
|
-
} as Response);
|
|
412
|
-
|
|
413
|
-
const result = await hiveRates.fetchRates();
|
|
414
|
-
expect(result).toBe(true);
|
|
415
|
-
|
|
416
|
-
const cryptoRates = hiveRates.getCryptoRates();
|
|
417
|
-
expect(cryptoRates.hive).toBeUndefined();
|
|
418
|
-
expect(cryptoRates.hbd).toBeUndefined();
|
|
419
|
-
});
|
|
420
|
-
|
|
421
|
-
it('should handle partial crypto rates', async () => {
|
|
422
|
-
mockExchange.mockHiveRate = 0.5;
|
|
423
|
-
mockExchange.mockHbdRate = 0; // Invalid
|
|
424
|
-
|
|
425
|
-
mockFetch.mockResolvedValue({
|
|
426
|
-
ok: true,
|
|
427
|
-
json: async () => ({
|
|
428
|
-
usd: { eur: 0.85 }
|
|
429
|
-
}),
|
|
430
|
-
} as Response);
|
|
431
|
-
|
|
432
|
-
await hiveRates.fetchRates();
|
|
433
|
-
|
|
434
|
-
const cryptoRates = hiveRates.getCryptoRates();
|
|
435
|
-
expect(cryptoRates.hive).toBe(0.5);
|
|
436
|
-
expect(cryptoRates.hbd).toBeUndefined();
|
|
437
|
-
|
|
438
|
-
// Should still calculate HIVE rates but not HBD rates
|
|
439
|
-
expect(hiveRates.getRate('EUR', 'HIVE')).toBeCloseTo(0.5 * 0.85);
|
|
440
|
-
expect(hiveRates.getRate('EUR', 'HBD')).toBeNull();
|
|
441
|
-
});
|
|
442
|
-
});
|
|
443
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { HiveRates } from '../../src/hive-rates';
|
|
2
|
-
|
|
3
|
-
const shouldRunIntegration = process.env.RUN_INTEGRATION === 'true';
|
|
4
|
-
|
|
5
|
-
describe('HiveRates Integration Test', () => {
|
|
6
|
-
(shouldRunIntegration ? it : it.skip)('should fetch real rates successfully', async () => {
|
|
7
|
-
const hiveRates = new HiveRates();
|
|
8
|
-
|
|
9
|
-
const result = await hiveRates.fetchRates();
|
|
10
|
-
expect(result).toBe(true);
|
|
11
|
-
|
|
12
|
-
// Check that we have some crypto rates
|
|
13
|
-
const cryptoRates = hiveRates.getCryptoRates();
|
|
14
|
-
expect(cryptoRates.hive).toBeGreaterThan(0);
|
|
15
|
-
expect(cryptoRates.hbd).toBeGreaterThan(0);
|
|
16
|
-
|
|
17
|
-
// Check that we have some fiat rates
|
|
18
|
-
const fiatRates = hiveRates.getFiatRates();
|
|
19
|
-
expect(Object.keys(fiatRates).length).toBeGreaterThan(0);
|
|
20
|
-
expect(fiatRates.EUR).toBeGreaterThan(0);
|
|
21
|
-
|
|
22
|
-
// Check that cross rates are calculated
|
|
23
|
-
const eurHiveRate = hiveRates.getRate('EUR', 'HIVE');
|
|
24
|
-
expect(eurHiveRate).toBeGreaterThan(0);
|
|
25
|
-
|
|
26
|
-
const gbpHbdRate = hiveRates.getRate('GBP', 'HBD');
|
|
27
|
-
expect(gbpHbdRate).toBeGreaterThan(0);
|
|
28
|
-
|
|
29
|
-
console.log('Sample rates:');
|
|
30
|
-
console.log(`HIVE: $${cryptoRates.hive?.toFixed(6)}`);
|
|
31
|
-
console.log(`HBD: $${cryptoRates.hbd?.toFixed(6)}`);
|
|
32
|
-
console.log(`EUR/HIVE: ${eurHiveRate?.toFixed(6)}`);
|
|
33
|
-
console.log(`GBP/HBD: ${gbpHbdRate?.toFixed(6)}`);
|
|
34
|
-
}, 30000); // 30 second timeout for real API calls
|
|
35
|
-
});
|
package/tests/metadata.spec.ts
DELETED
|
@@ -1,63 +0,0 @@
|
|
|
1
|
-
import { TimeAction } from '../src/actions';
|
|
2
|
-
import { Config } from '../src/config';
|
|
3
|
-
import { HIVE_STREAM_METADATA, getHiveStreamMetadata } from '../src/metadata';
|
|
4
|
-
|
|
5
|
-
describe('metadata exports', () => {
|
|
6
|
-
test('returns a stable frozen metadata object', () => {
|
|
7
|
-
const meta = getHiveStreamMetadata();
|
|
8
|
-
|
|
9
|
-
expect(meta).toBe(HIVE_STREAM_METADATA);
|
|
10
|
-
expect(Object.isFrozen(meta)).toBe(true);
|
|
11
|
-
expect(Object.isFrozen(meta.config)).toBe(true);
|
|
12
|
-
expect(Object.isFrozen(meta.subscriptions)).toBe(true);
|
|
13
|
-
expect(Object.isFrozen(meta.writeOperations)).toBe(true);
|
|
14
|
-
});
|
|
15
|
-
|
|
16
|
-
test('includes config defaults aligned with Config source', () => {
|
|
17
|
-
const map = new Map(HIVE_STREAM_METADATA.config.options.map((option) => [option.key, option.defaultValue]));
|
|
18
|
-
const builderMap = new Map(HIVE_STREAM_METADATA.config.options.map((option) => [option.key, option.builderKey]));
|
|
19
|
-
|
|
20
|
-
expect(map.get('JSON_ID')).toBe(Config.JSON_ID);
|
|
21
|
-
expect(map.get('PAYLOAD_IDENTIFIER')).toBe(Config.PAYLOAD_IDENTIFIER);
|
|
22
|
-
expect(map.get('HIVE_ENGINE_ID')).toBe(Config.HIVE_ENGINE_ID);
|
|
23
|
-
expect(map.get('BLOCK_CHECK_INTERVAL')).toBe(Config.BLOCK_CHECK_INTERVAL);
|
|
24
|
-
expect(builderMap.get('JSON_ID')).toBe('jsonId');
|
|
25
|
-
expect(builderMap.get('PAYLOAD_IDENTIFIER')).toBe('payloadIdentifier');
|
|
26
|
-
expect(builderMap.get('BLOCK_CHECK_INTERVAL')).toBe('blockCheckInterval');
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
test('includes expected subscription metadata', () => {
|
|
30
|
-
const transfer = HIVE_STREAM_METADATA.subscriptions.find((item) => item.method === 'onTransfer');
|
|
31
|
-
const customJsonId = HIVE_STREAM_METADATA.subscriptions.find((item) => item.method === 'onCustomJsonId');
|
|
32
|
-
|
|
33
|
-
expect(transfer).toBeDefined();
|
|
34
|
-
expect(transfer?.accountFilterBuiltIn).toBe(true);
|
|
35
|
-
|
|
36
|
-
expect(customJsonId).toBeDefined();
|
|
37
|
-
expect(customJsonId?.idFilterBuiltIn).toBe(true);
|
|
38
|
-
});
|
|
39
|
-
|
|
40
|
-
test('exposes valid time action values from TimeAction source', () => {
|
|
41
|
-
expect(HIVE_STREAM_METADATA.timeAction.validValues).toEqual(TimeAction.getValidTimeValues());
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test('lists contract triggers and supported operations', () => {
|
|
45
|
-
expect(HIVE_STREAM_METADATA.contracts.payload.supportedTriggers).toEqual([
|
|
46
|
-
'custom_json',
|
|
47
|
-
'transfer',
|
|
48
|
-
'time',
|
|
49
|
-
'escrow_transfer',
|
|
50
|
-
'escrow_approve',
|
|
51
|
-
'escrow_dispute',
|
|
52
|
-
'escrow_release',
|
|
53
|
-
'recurrent_transfer'
|
|
54
|
-
]);
|
|
55
|
-
|
|
56
|
-
expect(HIVE_STREAM_METADATA.contracts.payload.supportedOperations).toEqual([
|
|
57
|
-
'transfer',
|
|
58
|
-
'custom_json',
|
|
59
|
-
'escrow_transfer',
|
|
60
|
-
'recurrent_transfer'
|
|
61
|
-
]);
|
|
62
|
-
});
|
|
63
|
-
});
|
package/tests/setup.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { GlobalWithFetchMock } from 'jest-fetch-mock';
|
|
2
|
-
|
|
3
|
-
// (global as any).console = {
|
|
4
|
-
// log: jest.fn(), // console.log are ignored in tests
|
|
5
|
-
|
|
6
|
-
// // Keep native behaviour for other methods, use those to print out things in your own tests, not `console.log`
|
|
7
|
-
// error: console.error,
|
|
8
|
-
// warn: console.warn,
|
|
9
|
-
// info: console.info,
|
|
10
|
-
// debug: console.debug,
|
|
11
|
-
// };
|
|
12
|
-
|
|
13
|
-
const fetchMock = require('jest-fetch-mock');
|
|
14
|
-
const customGlobal: GlobalWithFetchMock = global as unknown as GlobalWithFetchMock;
|
|
15
|
-
|
|
16
|
-
// Safely assign fetch mock
|
|
17
|
-
if (!customGlobal.fetch) {
|
|
18
|
-
customGlobal.fetch = fetchMock;
|
|
19
|
-
} else {
|
|
20
|
-
Object.defineProperty(customGlobal, 'fetch', {
|
|
21
|
-
value: fetchMock,
|
|
22
|
-
writable: true,
|
|
23
|
-
configurable: true
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
customGlobal.fetchMock = customGlobal.fetch;
|
|
27
|
-
|
|
28
|
-
process.on('unhandledRejection', (error) => {
|
|
29
|
-
throw error; // Or whatever you like...
|
|
30
|
-
});
|