Skip to content

Commit b157f6c

Browse files
SharifIbrahimDevAnnakaee
andauthored
feat(sdk-mobile): Flutter plugin for property-token transfers (#636) (#697)
* feat(sdk-mobile): Flutter plugin for property-token transfers (#636) * feat(sdk): gas estimation, payment error tests, and RN minting (#634, #635, #637) --------- Co-authored-by: Annakaee <annakaee@example.com>
1 parent 672b6cc commit b157f6c

10 files changed

Lines changed: 1904 additions & 10 deletions

File tree

sdk/frontend/__tests__/gas.test.ts

Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
/**
2+
* Gas Estimation Tests (#634)
3+
*
4+
* Tests for the automatic gas-estimation utility with congestion-based
5+
* safety buffers.
6+
*/
7+
8+
import { describe, it, expect } from 'vitest';
9+
import {
10+
applyGasBuffer,
11+
estimateGasWithCongestion,
12+
congestionFromFillRatio,
13+
CongestionLevel,
14+
DEFAULT_BUFFERS,
15+
} from '../src/utils/gas';
16+
import type { GasEstimate } from '../src/utils/gas';
17+
18+
// ============================================================================
19+
// congestionFromFillRatio
20+
// ============================================================================
21+
22+
describe('congestionFromFillRatio', () => {
23+
it('returns Low for fill ratio below 0.4', () => {
24+
expect(congestionFromFillRatio(0)).toBe(CongestionLevel.Low);
25+
expect(congestionFromFillRatio(0.0)).toBe(CongestionLevel.Low);
26+
expect(congestionFromFillRatio(0.39)).toBe(CongestionLevel.Low);
27+
});
28+
29+
it('returns Medium for fill ratio 0.4 – 0.69', () => {
30+
expect(congestionFromFillRatio(0.4)).toBe(CongestionLevel.Medium);
31+
expect(congestionFromFillRatio(0.55)).toBe(CongestionLevel.Medium);
32+
expect(congestionFromFillRatio(0.699)).toBe(CongestionLevel.Medium);
33+
});
34+
35+
it('returns High for fill ratio 0.7 – 0.89', () => {
36+
expect(congestionFromFillRatio(0.7)).toBe(CongestionLevel.High);
37+
expect(congestionFromFillRatio(0.8)).toBe(CongestionLevel.High);
38+
expect(congestionFromFillRatio(0.899)).toBe(CongestionLevel.High);
39+
});
40+
41+
it('returns Extreme for fill ratio >= 0.9', () => {
42+
expect(congestionFromFillRatio(0.9)).toBe(CongestionLevel.Extreme);
43+
expect(congestionFromFillRatio(1.0)).toBe(CongestionLevel.Extreme);
44+
});
45+
46+
it('throws RangeError for values outside [0, 1]', () => {
47+
expect(() => congestionFromFillRatio(-0.1)).toThrow(RangeError);
48+
expect(() => congestionFromFillRatio(1.01)).toThrow(RangeError);
49+
});
50+
});
51+
52+
// ============================================================================
53+
// DEFAULT_BUFFERS
54+
// ============================================================================
55+
56+
describe('DEFAULT_BUFFERS', () => {
57+
it('has a buffer for every congestion level', () => {
58+
for (const level of Object.values(CongestionLevel)) {
59+
expect(DEFAULT_BUFFERS[level]).toBeDefined();
60+
expect(typeof DEFAULT_BUFFERS[level]).toBe('number');
61+
}
62+
});
63+
64+
it('buffers increase with congestion severity', () => {
65+
expect(DEFAULT_BUFFERS[CongestionLevel.Low]).toBeLessThan(
66+
DEFAULT_BUFFERS[CongestionLevel.Medium],
67+
);
68+
expect(DEFAULT_BUFFERS[CongestionLevel.Medium]).toBeLessThan(
69+
DEFAULT_BUFFERS[CongestionLevel.High],
70+
);
71+
expect(DEFAULT_BUFFERS[CongestionLevel.High]).toBeLessThan(
72+
DEFAULT_BUFFERS[CongestionLevel.Extreme],
73+
);
74+
});
75+
});
76+
77+
// ============================================================================
78+
// applyGasBuffer
79+
// ============================================================================
80+
81+
describe('applyGasBuffer', () => {
82+
describe('fixed buffer mode', () => {
83+
it('applies fixed buffer correctly', () => {
84+
const result: GasEstimate = applyGasBuffer(1_000_000n, {
85+
fixedBufferPercent: 10,
86+
});
87+
expect(result.rawGas).toBe(1_000_000n);
88+
expect(result.gasWithBuffer).toBe(1_100_000n);
89+
expect(result.bufferPercent).toBe(10);
90+
});
91+
92+
it('applies 0% buffer (no change)', () => {
93+
const result = applyGasBuffer(500_000n, { fixedBufferPercent: 0 });
94+
expect(result.gasWithBuffer).toBe(500_000n);
95+
});
96+
97+
it('applies 50% buffer', () => {
98+
const result = applyGasBuffer(200_000n, { fixedBufferPercent: 50 });
99+
expect(result.gasWithBuffer).toBe(300_000n);
100+
});
101+
102+
it('applies 100% buffer (doubles the gas)', () => {
103+
const result = applyGasBuffer(100_000n, { fixedBufferPercent: 100 });
104+
expect(result.gasWithBuffer).toBe(200_000n);
105+
});
106+
});
107+
108+
describe('congestion-based buffer mode', () => {
109+
it('defaults to Medium congestion when no override is given', () => {
110+
const result = applyGasBuffer(1_000_000n);
111+
expect(result.congestionLevel).toBe(CongestionLevel.Medium);
112+
expect(result.bufferPercent).toBe(DEFAULT_BUFFERS[CongestionLevel.Medium]);
113+
});
114+
115+
it('applies Low congestion buffer', () => {
116+
const result = applyGasBuffer(1_000_000n, {
117+
congestionOverride: CongestionLevel.Low,
118+
});
119+
expect(result.bufferPercent).toBe(DEFAULT_BUFFERS[CongestionLevel.Low]);
120+
const expected = 1_000_000n + (1_000_000n * BigInt(DEFAULT_BUFFERS[CongestionLevel.Low])) / 100n;
121+
expect(result.gasWithBuffer).toBe(expected);
122+
});
123+
124+
it('applies High congestion buffer', () => {
125+
const result = applyGasBuffer(1_000_000n, {
126+
congestionOverride: CongestionLevel.High,
127+
});
128+
expect(result.bufferPercent).toBe(DEFAULT_BUFFERS[CongestionLevel.High]);
129+
});
130+
131+
it('applies Extreme congestion buffer', () => {
132+
const result = applyGasBuffer(1_000_000n, {
133+
congestionOverride: CongestionLevel.Extreme,
134+
});
135+
expect(result.bufferPercent).toBe(DEFAULT_BUFFERS[CongestionLevel.Extreme]);
136+
});
137+
138+
it('supports custom buffersByLevel overrides', () => {
139+
const result = applyGasBuffer(1_000_000n, {
140+
congestionOverride: CongestionLevel.High,
141+
buffersByLevel: { [CongestionLevel.High]: 25 },
142+
});
143+
expect(result.bufferPercent).toBe(25);
144+
expect(result.gasWithBuffer).toBe(1_250_000n);
145+
});
146+
147+
it('leaves default levels intact when only one is overridden', () => {
148+
const result = applyGasBuffer(1_000_000n, {
149+
congestionOverride: CongestionLevel.Low,
150+
buffersByLevel: { [CongestionLevel.High]: 99 },
151+
});
152+
expect(result.bufferPercent).toBe(DEFAULT_BUFFERS[CongestionLevel.Low]);
153+
});
154+
});
155+
156+
describe('edge cases', () => {
157+
it('handles rawGas of 0', () => {
158+
const result = applyGasBuffer(0n, { fixedBufferPercent: 50 });
159+
expect(result.rawGas).toBe(0n);
160+
expect(result.gasWithBuffer).toBe(0n);
161+
});
162+
163+
it('throws RangeError for negative rawGas', () => {
164+
expect(() => applyGasBuffer(-1n)).toThrow(RangeError);
165+
});
166+
167+
it('throws RangeError for bufferPercent > 200', () => {
168+
expect(() => applyGasBuffer(1000n, { fixedBufferPercent: 201 })).toThrow(RangeError);
169+
});
170+
171+
it('throws RangeError for negative bufferPercent', () => {
172+
expect(() => applyGasBuffer(1000n, { fixedBufferPercent: -1 })).toThrow(RangeError);
173+
});
174+
175+
it('returns correct shape for GasEstimate', () => {
176+
const result = applyGasBuffer(500n, { fixedBufferPercent: 20 });
177+
expect(result).toHaveProperty('rawGas');
178+
expect(result).toHaveProperty('gasWithBuffer');
179+
expect(result).toHaveProperty('bufferPercent');
180+
expect(result).toHaveProperty('congestionLevel');
181+
});
182+
});
183+
});
184+
185+
// ============================================================================
186+
// estimateGasWithCongestion
187+
// ============================================================================
188+
189+
describe('estimateGasWithCongestion', () => {
190+
it('selects Low buffer for low fill ratio', () => {
191+
const result = estimateGasWithCongestion(1_000_000n, 0.2);
192+
expect(result.congestionLevel).toBe(CongestionLevel.Low);
193+
expect(result.bufferPercent).toBe(DEFAULT_BUFFERS[CongestionLevel.Low]);
194+
});
195+
196+
it('selects Medium buffer for medium fill ratio', () => {
197+
const result = estimateGasWithCongestion(1_000_000n, 0.55);
198+
expect(result.congestionLevel).toBe(CongestionLevel.Medium);
199+
});
200+
201+
it('selects High buffer for high fill ratio', () => {
202+
const result = estimateGasWithCongestion(1_000_000n, 0.8);
203+
expect(result.congestionLevel).toBe(CongestionLevel.High);
204+
expect(result.gasWithBuffer).toBe(1_350_000n);
205+
});
206+
207+
it('selects Extreme buffer for very high fill ratio', () => {
208+
const result = estimateGasWithCongestion(1_000_000n, 0.95);
209+
expect(result.congestionLevel).toBe(CongestionLevel.Extreme);
210+
expect(result.gasWithBuffer).toBe(1_500_000n);
211+
});
212+
213+
it('supports custom buffersByLevel', () => {
214+
const result = estimateGasWithCongestion(1_000_000n, 0.8, {
215+
buffersByLevel: { [CongestionLevel.High]: 40 },
216+
});
217+
expect(result.bufferPercent).toBe(40);
218+
expect(result.gasWithBuffer).toBe(1_400_000n);
219+
});
220+
221+
it('throws for invalid fill ratio', () => {
222+
expect(() => estimateGasWithCongestion(1_000_000n, 1.5)).toThrow(RangeError);
223+
});
224+
});

0 commit comments

Comments
 (0)