@xochi/client 0.0.0-stage → 0.1.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/CHANGELOG.md +54 -0
- package/LICENSE +21 -0
- package/README.md +119 -2
- package/dist/cjs/claim.d.ts +33 -0
- package/dist/cjs/claim.js +44 -0
- package/dist/cjs/fee.d.ts +247 -0
- package/dist/cjs/fee.js +295 -0
- package/dist/cjs/index.d.ts +18 -0
- package/dist/cjs/index.js +33 -0
- package/dist/cjs/machine/claimInfo.d.ts +29 -0
- package/dist/cjs/machine/claimInfo.js +26 -0
- package/dist/cjs/machine/decisions.d.ts +452 -0
- package/dist/cjs/machine/decisions.js +665 -0
- package/dist/cjs/machine/deposit.d.ts +113 -0
- package/dist/cjs/machine/deposit.js +265 -0
- package/dist/cjs/machine/index.d.ts +23 -0
- package/dist/cjs/machine/index.js +53 -0
- package/dist/cjs/machine/machine.d.ts +409 -0
- package/dist/cjs/machine/machine.js +1615 -0
- package/dist/cjs/machine/phase.d.ts +24 -0
- package/dist/cjs/machine/phase.js +45 -0
- package/dist/cjs/machine/quoteChecks.d.ts +41 -0
- package/dist/cjs/machine/quoteChecks.js +82 -0
- package/dist/cjs/machine/receipt.d.ts +151 -0
- package/dist/cjs/machine/receipt.js +69 -0
- package/dist/cjs/machine/recipientEcho.d.ts +16 -0
- package/dist/cjs/machine/recipientEcho.js +27 -0
- package/dist/cjs/machine/solverPin.d.ts +110 -0
- package/dist/cjs/machine/solverPin.js +214 -0
- package/dist/cjs/machine/state.d.ts +167 -0
- package/dist/cjs/machine/state.js +31 -0
- package/dist/cjs/machine/transition.d.ts +15 -0
- package/dist/cjs/machine/transition.js +20 -0
- package/dist/cjs/machine/validateRequest.d.ts +15 -0
- package/dist/cjs/machine/validateRequest.js +127 -0
- package/dist/cjs/machine/view.d.ts +3 -0
- package/dist/cjs/machine/view.js +74 -0
- package/dist/cjs/machine/wire.d.ts +527 -0
- package/dist/cjs/machine/wire.js +280 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/shared/api.d.ts +9 -0
- package/dist/cjs/shared/api.js +5 -0
- package/dist/cjs/shared/chains.d.ts +243 -0
- package/dist/cjs/shared/chains.js +250 -0
- package/dist/cjs/shared/eip712.d.ts +44 -0
- package/dist/cjs/shared/eip712.js +64 -0
- package/dist/cjs/shared/index.d.ts +15 -0
- package/dist/cjs/shared/index.js +31 -0
- package/dist/cjs/shared/intentStream.d.ts +74 -0
- package/dist/cjs/shared/intentStream.js +59 -0
- package/dist/cjs/shared/intents.d.ts +88 -0
- package/dist/cjs/shared/intents.js +227 -0
- package/dist/cjs/shared/schemas.d.ts +928 -0
- package/dist/cjs/shared/schemas.js +524 -0
- package/dist/cjs/shared/stealth.d.ts +53 -0
- package/dist/cjs/shared/stealth.js +68 -0
- package/dist/cjs/shared/trading.d.ts +153 -0
- package/dist/cjs/shared/trading.js +185 -0
- package/dist/cjs/shared/types.d.ts +37 -0
- package/dist/cjs/shared/types.js +7 -0
- package/dist/cjs/shared/validators.d.ts +30 -0
- package/dist/cjs/shared/validators.js +79 -0
- package/dist/cjs/transport/client.d.ts +234 -0
- package/dist/cjs/transport/client.js +1456 -0
- package/dist/esm/claim.d.ts +33 -0
- package/dist/esm/claim.js +41 -0
- package/dist/esm/fee.d.ts +247 -0
- package/dist/esm/fee.js +285 -0
- package/dist/esm/index.d.ts +18 -0
- package/dist/esm/index.js +17 -0
- package/dist/esm/machine/claimInfo.d.ts +29 -0
- package/dist/esm/machine/claimInfo.js +23 -0
- package/dist/esm/machine/decisions.d.ts +452 -0
- package/dist/esm/machine/decisions.js +640 -0
- package/dist/esm/machine/deposit.d.ts +113 -0
- package/dist/esm/machine/deposit.js +260 -0
- package/dist/esm/machine/index.d.ts +23 -0
- package/dist/esm/machine/index.js +23 -0
- package/dist/esm/machine/machine.d.ts +409 -0
- package/dist/esm/machine/machine.js +1609 -0
- package/dist/esm/machine/phase.d.ts +24 -0
- package/dist/esm/machine/phase.js +42 -0
- package/dist/esm/machine/quoteChecks.d.ts +41 -0
- package/dist/esm/machine/quoteChecks.js +78 -0
- package/dist/esm/machine/receipt.d.ts +151 -0
- package/dist/esm/machine/receipt.js +64 -0
- package/dist/esm/machine/recipientEcho.d.ts +16 -0
- package/dist/esm/machine/recipientEcho.js +24 -0
- package/dist/esm/machine/solverPin.d.ts +110 -0
- package/dist/esm/machine/solverPin.js +210 -0
- package/dist/esm/machine/state.d.ts +167 -0
- package/dist/esm/machine/state.js +28 -0
- package/dist/esm/machine/transition.d.ts +15 -0
- package/dist/esm/machine/transition.js +17 -0
- package/dist/esm/machine/validateRequest.d.ts +15 -0
- package/dist/esm/machine/validateRequest.js +123 -0
- package/dist/esm/machine/view.d.ts +3 -0
- package/dist/esm/machine/view.js +71 -0
- package/dist/esm/machine/wire.d.ts +527 -0
- package/dist/esm/machine/wire.js +266 -0
- package/dist/esm/shared/api.d.ts +9 -0
- package/dist/esm/shared/api.js +4 -0
- package/dist/esm/shared/chains.d.ts +243 -0
- package/dist/esm/shared/chains.js +236 -0
- package/dist/esm/shared/eip712.d.ts +44 -0
- package/dist/esm/shared/eip712.js +61 -0
- package/dist/esm/shared/index.d.ts +15 -0
- package/dist/esm/shared/index.js +15 -0
- package/dist/esm/shared/intentStream.d.ts +74 -0
- package/dist/esm/shared/intentStream.js +55 -0
- package/dist/esm/shared/intents.d.ts +88 -0
- package/dist/esm/shared/intents.js +213 -0
- package/dist/esm/shared/schemas.d.ts +928 -0
- package/dist/esm/shared/schemas.js +521 -0
- package/dist/esm/shared/stealth.d.ts +53 -0
- package/dist/esm/shared/stealth.js +64 -0
- package/dist/esm/shared/trading.d.ts +153 -0
- package/dist/esm/shared/trading.js +182 -0
- package/dist/esm/shared/types.d.ts +37 -0
- package/dist/esm/shared/types.js +6 -0
- package/dist/esm/shared/validators.d.ts +30 -0
- package/dist/esm/shared/validators.js +74 -0
- package/dist/esm/transport/client.d.ts +234 -0
- package/dist/esm/transport/client.js +1447 -0
- package/package.json +61 -4
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trading Constants
|
|
3
|
+
*
|
|
4
|
+
* Shared trading configuration for slippage, quotes, and limits.
|
|
5
|
+
*/
|
|
6
|
+
/** Default slippage in basis points (0.5%) */
|
|
7
|
+
export declare const DEFAULT_SLIPPAGE_BPS = 50;
|
|
8
|
+
/** Available slippage options in basis points */
|
|
9
|
+
export declare const SLIPPAGE_OPTIONS: readonly [10, 50, 100, 200];
|
|
10
|
+
export type SlippageOption = (typeof SLIPPAGE_OPTIONS)[number];
|
|
11
|
+
/** Slippage presets with labels */
|
|
12
|
+
export declare const SLIPPAGE_PRESETS: {
|
|
13
|
+
readonly low: 10;
|
|
14
|
+
readonly medium: 50;
|
|
15
|
+
readonly high: 100;
|
|
16
|
+
};
|
|
17
|
+
/** Quote expiry in seconds */
|
|
18
|
+
export declare const QUOTE_EXPIRY_SEC = 30;
|
|
19
|
+
/** Maximum retries for failed quotes */
|
|
20
|
+
export declare const MAX_QUOTE_RETRIES = 3;
|
|
21
|
+
/** Maximum decimal places for token amounts */
|
|
22
|
+
export declare const MAX_TOKEN_DECIMALS = 18;
|
|
23
|
+
/** Minimum trade amount in USD */
|
|
24
|
+
export declare const MIN_TRADE_USD = 1;
|
|
25
|
+
/** Maximum slippage percentage */
|
|
26
|
+
export declare const MAX_SLIPPAGE_PERCENT = 50;
|
|
27
|
+
/** Minimum slippage percentage */
|
|
28
|
+
export declare const MIN_SLIPPAGE_PERCENT = 0.01;
|
|
29
|
+
/**
|
|
30
|
+
* Hard ceiling on how far below market a fill may be before execution is
|
|
31
|
+
* refused. This is all-in value loss (fees + fixed network minimum + market
|
|
32
|
+
* slippage) versus the live market rate, not the user's configurable slippage
|
|
33
|
+
* tolerance. Protects users from executing trades -- typically dust orders --
|
|
34
|
+
* where costs eat more than half the notional.
|
|
35
|
+
*/
|
|
36
|
+
export declare const MAX_PRICE_IMPACT_PERCENT = 50;
|
|
37
|
+
/**
|
|
38
|
+
* Minimum trust score for Aztec L2 shielded settlement (the Private privacy
|
|
39
|
+
* level). L1 stealth (ERC-5564) is NOT trust-gated: privacy is free by default,
|
|
40
|
+
* so any wallet can settle to a one-time stealth address and simply pays its own
|
|
41
|
+
* trust-tier fee. Only the deeper Aztec-shielded tiers -- Private (50+) and
|
|
42
|
+
* Sovereign (75+), both reached via pxe-bridge -- require trust.
|
|
43
|
+
*/
|
|
44
|
+
export declare const SHIELDED_MIN_SCORE = 50;
|
|
45
|
+
/** Trust score thresholds by tier */
|
|
46
|
+
export declare const TRUST_THRESHOLDS: {
|
|
47
|
+
readonly trusted: 25;
|
|
48
|
+
readonly verified: 50;
|
|
49
|
+
readonly premium: 75;
|
|
50
|
+
readonly institutional: 100;
|
|
51
|
+
};
|
|
52
|
+
/** Basis points denominator (1 bps = 0.01%) */
|
|
53
|
+
export declare const BPS_DENOMINATOR = 10000;
|
|
54
|
+
/** Maximum deadline offset in seconds (1 hour) */
|
|
55
|
+
export declare const MAX_DEADLINE_OFFSET_SEC = 3600;
|
|
56
|
+
/**
|
|
57
|
+
* Server-side ceiling on a quote request's `deadline`, in seconds from now.
|
|
58
|
+
*
|
|
59
|
+
* Deliberately looser than MAX_DEADLINE_OFFSET_SEC, which is the CLIENT's rule
|
|
60
|
+
* (src/utils/validators.ts) and the value the frontend actually sends. This is
|
|
61
|
+
* the outer bound the API will accept from anyone, sized so an agent or a device
|
|
62
|
+
* with a skewed clock is not rejected for asking a reasonable question.
|
|
63
|
+
*
|
|
64
|
+
* The reason there is a ceiling at all: `deadline` is what the user signs into
|
|
65
|
+
* the intent EIP-712, so an unbounded value is an authorization with no
|
|
66
|
+
* expiry -- and `decideReconcile` treats "past the signed deadline" as the point
|
|
67
|
+
* where an in-doubt intent can no longer move funds.
|
|
68
|
+
*/
|
|
69
|
+
export declare const MAX_QUOTE_DEADLINE_FUTURE_SEC: number;
|
|
70
|
+
/**
|
|
71
|
+
* How far in the PAST a quote `deadline` may be and still be accepted, in
|
|
72
|
+
* seconds. Pure clock-skew tolerance: no correct client asks for a deadline that
|
|
73
|
+
* has already passed, but one whose clock is behind might.
|
|
74
|
+
*
|
|
75
|
+
* A past-dated deadline is not inert data: the abandoned-deposit sweep reads
|
|
76
|
+
* `deadline` to decide when a deposit route has died, so `deadline: 1` would
|
|
77
|
+
* mean "terminalise this live route on the next cron tick". The sweep gates on
|
|
78
|
+
* the server-set `created_at` too; this is the other half: the value never
|
|
79
|
+
* gets stored in the first place.
|
|
80
|
+
*/
|
|
81
|
+
export declare const MAX_QUOTE_DEADLINE_PAST_SEC = 3600;
|
|
82
|
+
/**
|
|
83
|
+
* Sanity bound on the SOLVER-supplied `deposit_deadline`, in seconds from the
|
|
84
|
+
* quote, applied only when Xochi persists it.
|
|
85
|
+
*
|
|
86
|
+
* The client treats this field as untrusted: `POLL_CEILING_MAX_MS` exists
|
|
87
|
+
* because a malformed or hostile `deposit_deadline` far in the future must not
|
|
88
|
+
* turn the poll into a permanent background request loop. Persisting it makes
|
|
89
|
+
* the server trust it more than the browser does, and it is the PRIMARY gate
|
|
90
|
+
* on the abandoned-deposit sweep (`COALESCE(deposit_deadline, deadline)`), so
|
|
91
|
+
* one bad value -- a misparsed `XOCHI_DEPOSIT_DEADLINE_SECONDS`, a solver bug
|
|
92
|
+
* -- would make every deposit row permanently and silently unsweepable.
|
|
93
|
+
*
|
|
94
|
+
* Riddler's default is 1800s, so this is two orders of magnitude of headroom: it
|
|
95
|
+
* rejects nothing a correctly configured solver can mint. A value outside it is
|
|
96
|
+
* stored as NULL, which degrades the sweep to the quote `deadline` rather than
|
|
97
|
+
* to no gate at all. The value SERVED to the client is never altered -- it is
|
|
98
|
+
* covered by the deposit attestation signature, so changing it would break
|
|
99
|
+
* client-side verification.
|
|
100
|
+
*/
|
|
101
|
+
export declare const MAX_DEPOSIT_WINDOW_SEC: number;
|
|
102
|
+
/** Maximum proof age in seconds (1 hour) -- proofs older than this are rejected server-side */
|
|
103
|
+
export declare const MAX_PROOF_AGE_SEC = 3600;
|
|
104
|
+
/** Grace period for rotated provider sets in seconds (24 hours) */
|
|
105
|
+
export declare const PROVIDER_SET_GRACE_PERIOD_SEC = 86400;
|
|
106
|
+
/** Ethereum address length including 0x prefix */
|
|
107
|
+
export declare const ETH_ADDRESS_LENGTH = 42;
|
|
108
|
+
/** Max slippage in basis points */
|
|
109
|
+
export declare const MAX_SLIPPAGE_BPS: number;
|
|
110
|
+
/** Multipliers for attestation scoring within a category */
|
|
111
|
+
export declare const ATTESTATION_MULTIPLIERS: {
|
|
112
|
+
readonly first: 1;
|
|
113
|
+
readonly second: 0.25;
|
|
114
|
+
readonly subsequent: 0.1;
|
|
115
|
+
};
|
|
116
|
+
/** Default query limit for paginated API responses */
|
|
117
|
+
export declare const DEFAULT_QUERY_LIMIT = 50;
|
|
118
|
+
/** Maximum query limit for announcement scanning */
|
|
119
|
+
export declare const MAX_ANNOUNCEMENT_LIMIT = 1000;
|
|
120
|
+
/** Default announcement query limit */
|
|
121
|
+
export declare const DEFAULT_ANNOUNCEMENT_LIMIT = 100;
|
|
122
|
+
/** Rate limit window in milliseconds (15 minutes) */
|
|
123
|
+
export declare const RATE_LIMIT_WINDOW_MS: number;
|
|
124
|
+
/** Maximum rate-limited attempts per window */
|
|
125
|
+
export declare const RATE_LIMIT_MAX_ATTEMPTS = 5;
|
|
126
|
+
/** JWT token expiry in hours */
|
|
127
|
+
export declare const JWT_EXPIRY_HOURS = 4;
|
|
128
|
+
/** Tier proof expiry in milliseconds (7 days) */
|
|
129
|
+
export declare const TIER_PROOF_EXPIRY_MS: number;
|
|
130
|
+
/** Max rate limit store size before cleanup */
|
|
131
|
+
export declare const RATE_LIMIT_STORE_MAX = 10000;
|
|
132
|
+
/** Base delay for failed auth in milliseconds */
|
|
133
|
+
export declare const AUTH_FAILURE_BASE_DELAY_MS = 500;
|
|
134
|
+
/** Max delay for failed auth in milliseconds */
|
|
135
|
+
export declare const AUTH_FAILURE_MAX_DELAY_MS = 5000;
|
|
136
|
+
/** Max demo code length */
|
|
137
|
+
export declare const MAX_DEMO_CODE_LENGTH = 100;
|
|
138
|
+
/** Mock spread factor (1% spread = 99/100) */
|
|
139
|
+
export declare const MOCK_SPREAD_NUMERATOR = 99n;
|
|
140
|
+
export declare const MOCK_SPREAD_DENOMINATOR = 100n;
|
|
141
|
+
/** All trading constants in one object */
|
|
142
|
+
export declare const TRADING: {
|
|
143
|
+
readonly defaultSlippageBps: 50;
|
|
144
|
+
readonly slippageOptions: readonly [10, 50, 100, 200];
|
|
145
|
+
readonly quoteExpirySec: 30;
|
|
146
|
+
readonly maxQuoteRetries: 3;
|
|
147
|
+
readonly maxTokenDecimals: 18;
|
|
148
|
+
readonly minTradeUsd: 1;
|
|
149
|
+
readonly maxSlippagePercent: 50;
|
|
150
|
+
readonly minSlippagePercent: 0.01;
|
|
151
|
+
readonly maxPriceImpactPercent: 50;
|
|
152
|
+
readonly shieldedMinScore: 50;
|
|
153
|
+
};
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trading Constants
|
|
3
|
+
*
|
|
4
|
+
* Shared trading configuration for slippage, quotes, and limits.
|
|
5
|
+
*/
|
|
6
|
+
// ============================================================
|
|
7
|
+
// Slippage Configuration
|
|
8
|
+
// ============================================================
|
|
9
|
+
/** Default slippage in basis points (0.5%) */
|
|
10
|
+
export const DEFAULT_SLIPPAGE_BPS = 50;
|
|
11
|
+
/** Available slippage options in basis points */
|
|
12
|
+
export const SLIPPAGE_OPTIONS = [10, 50, 100, 200];
|
|
13
|
+
/** Slippage presets with labels */
|
|
14
|
+
export const SLIPPAGE_PRESETS = {
|
|
15
|
+
low: 10, // 0.1%
|
|
16
|
+
medium: 50, // 0.5%
|
|
17
|
+
high: 100, // 1%
|
|
18
|
+
};
|
|
19
|
+
// ============================================================
|
|
20
|
+
// Quote Configuration
|
|
21
|
+
// ============================================================
|
|
22
|
+
/** Quote expiry in seconds */
|
|
23
|
+
export const QUOTE_EXPIRY_SEC = 30;
|
|
24
|
+
/** Maximum retries for failed quotes */
|
|
25
|
+
export const MAX_QUOTE_RETRIES = 3;
|
|
26
|
+
// ============================================================
|
|
27
|
+
// Trading Limits
|
|
28
|
+
// ============================================================
|
|
29
|
+
/** Maximum decimal places for token amounts */
|
|
30
|
+
export const MAX_TOKEN_DECIMALS = 18;
|
|
31
|
+
/** Minimum trade amount in USD */
|
|
32
|
+
export const MIN_TRADE_USD = 1;
|
|
33
|
+
/** Maximum slippage percentage */
|
|
34
|
+
export const MAX_SLIPPAGE_PERCENT = 50;
|
|
35
|
+
/** Minimum slippage percentage */
|
|
36
|
+
export const MIN_SLIPPAGE_PERCENT = 0.01;
|
|
37
|
+
/**
|
|
38
|
+
* Hard ceiling on how far below market a fill may be before execution is
|
|
39
|
+
* refused. This is all-in value loss (fees + fixed network minimum + market
|
|
40
|
+
* slippage) versus the live market rate, not the user's configurable slippage
|
|
41
|
+
* tolerance. Protects users from executing trades -- typically dust orders --
|
|
42
|
+
* where costs eat more than half the notional.
|
|
43
|
+
*/
|
|
44
|
+
export const MAX_PRICE_IMPACT_PERCENT = 50;
|
|
45
|
+
// ============================================================
|
|
46
|
+
// Trust Thresholds
|
|
47
|
+
// ============================================================
|
|
48
|
+
/**
|
|
49
|
+
* Minimum trust score for Aztec L2 shielded settlement (the Private privacy
|
|
50
|
+
* level). L1 stealth (ERC-5564) is NOT trust-gated: privacy is free by default,
|
|
51
|
+
* so any wallet can settle to a one-time stealth address and simply pays its own
|
|
52
|
+
* trust-tier fee. Only the deeper Aztec-shielded tiers -- Private (50+) and
|
|
53
|
+
* Sovereign (75+), both reached via pxe-bridge -- require trust.
|
|
54
|
+
*/
|
|
55
|
+
export const SHIELDED_MIN_SCORE = 50;
|
|
56
|
+
/** Trust score thresholds by tier */
|
|
57
|
+
export const TRUST_THRESHOLDS = {
|
|
58
|
+
trusted: 25,
|
|
59
|
+
verified: 50,
|
|
60
|
+
premium: 75,
|
|
61
|
+
institutional: 100,
|
|
62
|
+
};
|
|
63
|
+
// ============================================================
|
|
64
|
+
// Numeric Constants
|
|
65
|
+
// ============================================================
|
|
66
|
+
/** Basis points denominator (1 bps = 0.01%) */
|
|
67
|
+
export const BPS_DENOMINATOR = 10_000;
|
|
68
|
+
/** Maximum deadline offset in seconds (1 hour) */
|
|
69
|
+
export const MAX_DEADLINE_OFFSET_SEC = 3600;
|
|
70
|
+
/**
|
|
71
|
+
* Server-side ceiling on a quote request's `deadline`, in seconds from now.
|
|
72
|
+
*
|
|
73
|
+
* Deliberately looser than MAX_DEADLINE_OFFSET_SEC, which is the CLIENT's rule
|
|
74
|
+
* (src/utils/validators.ts) and the value the frontend actually sends. This is
|
|
75
|
+
* the outer bound the API will accept from anyone, sized so an agent or a device
|
|
76
|
+
* with a skewed clock is not rejected for asking a reasonable question.
|
|
77
|
+
*
|
|
78
|
+
* The reason there is a ceiling at all: `deadline` is what the user signs into
|
|
79
|
+
* the intent EIP-712, so an unbounded value is an authorization with no
|
|
80
|
+
* expiry -- and `decideReconcile` treats "past the signed deadline" as the point
|
|
81
|
+
* where an in-doubt intent can no longer move funds.
|
|
82
|
+
*/
|
|
83
|
+
export const MAX_QUOTE_DEADLINE_FUTURE_SEC = 24 * 3600;
|
|
84
|
+
/**
|
|
85
|
+
* How far in the PAST a quote `deadline` may be and still be accepted, in
|
|
86
|
+
* seconds. Pure clock-skew tolerance: no correct client asks for a deadline that
|
|
87
|
+
* has already passed, but one whose clock is behind might.
|
|
88
|
+
*
|
|
89
|
+
* A past-dated deadline is not inert data: the abandoned-deposit sweep reads
|
|
90
|
+
* `deadline` to decide when a deposit route has died, so `deadline: 1` would
|
|
91
|
+
* mean "terminalise this live route on the next cron tick". The sweep gates on
|
|
92
|
+
* the server-set `created_at` too; this is the other half: the value never
|
|
93
|
+
* gets stored in the first place.
|
|
94
|
+
*/
|
|
95
|
+
export const MAX_QUOTE_DEADLINE_PAST_SEC = 3600;
|
|
96
|
+
/**
|
|
97
|
+
* Sanity bound on the SOLVER-supplied `deposit_deadline`, in seconds from the
|
|
98
|
+
* quote, applied only when Xochi persists it.
|
|
99
|
+
*
|
|
100
|
+
* The client treats this field as untrusted: `POLL_CEILING_MAX_MS` exists
|
|
101
|
+
* because a malformed or hostile `deposit_deadline` far in the future must not
|
|
102
|
+
* turn the poll into a permanent background request loop. Persisting it makes
|
|
103
|
+
* the server trust it more than the browser does, and it is the PRIMARY gate
|
|
104
|
+
* on the abandoned-deposit sweep (`COALESCE(deposit_deadline, deadline)`), so
|
|
105
|
+
* one bad value -- a misparsed `XOCHI_DEPOSIT_DEADLINE_SECONDS`, a solver bug
|
|
106
|
+
* -- would make every deposit row permanently and silently unsweepable.
|
|
107
|
+
*
|
|
108
|
+
* Riddler's default is 1800s, so this is two orders of magnitude of headroom: it
|
|
109
|
+
* rejects nothing a correctly configured solver can mint. A value outside it is
|
|
110
|
+
* stored as NULL, which degrades the sweep to the quote `deadline` rather than
|
|
111
|
+
* to no gate at all. The value SERVED to the client is never altered -- it is
|
|
112
|
+
* covered by the deposit attestation signature, so changing it would break
|
|
113
|
+
* client-side verification.
|
|
114
|
+
*/
|
|
115
|
+
export const MAX_DEPOSIT_WINDOW_SEC = 24 * 3600;
|
|
116
|
+
/** Maximum proof age in seconds (1 hour) -- proofs older than this are rejected server-side */
|
|
117
|
+
export const MAX_PROOF_AGE_SEC = 3600;
|
|
118
|
+
/** Grace period for rotated provider sets in seconds (24 hours) */
|
|
119
|
+
export const PROVIDER_SET_GRACE_PERIOD_SEC = 86400;
|
|
120
|
+
/** Ethereum address length including 0x prefix */
|
|
121
|
+
export const ETH_ADDRESS_LENGTH = 42;
|
|
122
|
+
/** Max slippage in basis points */
|
|
123
|
+
export const MAX_SLIPPAGE_BPS = MAX_SLIPPAGE_PERCENT * 100;
|
|
124
|
+
// ============================================================
|
|
125
|
+
// Attestation Diminishing Returns
|
|
126
|
+
// ============================================================
|
|
127
|
+
/** Multipliers for attestation scoring within a category */
|
|
128
|
+
export const ATTESTATION_MULTIPLIERS = {
|
|
129
|
+
first: 1.0,
|
|
130
|
+
second: 0.25,
|
|
131
|
+
subsequent: 0.1,
|
|
132
|
+
};
|
|
133
|
+
// ============================================================
|
|
134
|
+
// Query Limits
|
|
135
|
+
// ============================================================
|
|
136
|
+
/** Default query limit for paginated API responses */
|
|
137
|
+
export const DEFAULT_QUERY_LIMIT = 50;
|
|
138
|
+
/** Maximum query limit for announcement scanning */
|
|
139
|
+
export const MAX_ANNOUNCEMENT_LIMIT = 1000;
|
|
140
|
+
/** Default announcement query limit */
|
|
141
|
+
export const DEFAULT_ANNOUNCEMENT_LIMIT = 100;
|
|
142
|
+
// ============================================================
|
|
143
|
+
// Auth & Rate Limiting
|
|
144
|
+
// ============================================================
|
|
145
|
+
/** Rate limit window in milliseconds (15 minutes) */
|
|
146
|
+
export const RATE_LIMIT_WINDOW_MS = 15 * 60 * 1000;
|
|
147
|
+
/** Maximum rate-limited attempts per window */
|
|
148
|
+
export const RATE_LIMIT_MAX_ATTEMPTS = 5;
|
|
149
|
+
/** JWT token expiry in hours */
|
|
150
|
+
export const JWT_EXPIRY_HOURS = 4;
|
|
151
|
+
/** Tier proof expiry in milliseconds (7 days) */
|
|
152
|
+
export const TIER_PROOF_EXPIRY_MS = 7 * 24 * 60 * 60 * 1000;
|
|
153
|
+
/** Max rate limit store size before cleanup */
|
|
154
|
+
export const RATE_LIMIT_STORE_MAX = 10_000;
|
|
155
|
+
/** Base delay for failed auth in milliseconds */
|
|
156
|
+
export const AUTH_FAILURE_BASE_DELAY_MS = 500;
|
|
157
|
+
/** Max delay for failed auth in milliseconds */
|
|
158
|
+
export const AUTH_FAILURE_MAX_DELAY_MS = 5000;
|
|
159
|
+
/** Max demo code length */
|
|
160
|
+
export const MAX_DEMO_CODE_LENGTH = 100;
|
|
161
|
+
// ============================================================
|
|
162
|
+
// Mock Spread
|
|
163
|
+
// ============================================================
|
|
164
|
+
/** Mock spread factor (1% spread = 99/100) */
|
|
165
|
+
export const MOCK_SPREAD_NUMERATOR = 99n;
|
|
166
|
+
export const MOCK_SPREAD_DENOMINATOR = 100n;
|
|
167
|
+
// ============================================================
|
|
168
|
+
// Bundled Trading Config
|
|
169
|
+
// ============================================================
|
|
170
|
+
/** All trading constants in one object */
|
|
171
|
+
export const TRADING = {
|
|
172
|
+
defaultSlippageBps: DEFAULT_SLIPPAGE_BPS,
|
|
173
|
+
slippageOptions: SLIPPAGE_OPTIONS,
|
|
174
|
+
quoteExpirySec: QUOTE_EXPIRY_SEC,
|
|
175
|
+
maxQuoteRetries: MAX_QUOTE_RETRIES,
|
|
176
|
+
maxTokenDecimals: MAX_TOKEN_DECIMALS,
|
|
177
|
+
minTradeUsd: MIN_TRADE_USD,
|
|
178
|
+
maxSlippagePercent: MAX_SLIPPAGE_PERCENT,
|
|
179
|
+
minSlippagePercent: MIN_SLIPPAGE_PERCENT,
|
|
180
|
+
maxPriceImpactPercent: MAX_PRICE_IMPACT_PERCENT,
|
|
181
|
+
shieldedMinScore: SHIELDED_MIN_SCORE,
|
|
182
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Types
|
|
3
|
+
*
|
|
4
|
+
* Type definitions used across frontend and backend.
|
|
5
|
+
*/
|
|
6
|
+
/** Lowercase tier id used on the wire + in the fee breakdown. */
|
|
7
|
+
export type Tier = "standard" | "trusted" | "verified" | "premium" | "institutional";
|
|
8
|
+
/**
|
|
9
|
+
* Itemized fee breakdown for a quote (economics.md Part 1, "Frontend display spec").
|
|
10
|
+
* Three additive layers on a never-discounted cost floor: solver spread + gas
|
|
11
|
+
* floor (Riddler), venue fee (Xochi), routing fee (Raxol -> buyback). Amounts are
|
|
12
|
+
* destination-token smallest units (strings); rates are bps. Discounts carve
|
|
13
|
+
* venue + routing only, never the solver floor.
|
|
14
|
+
*/
|
|
15
|
+
export interface FeeBreakdown {
|
|
16
|
+
tier: Tier;
|
|
17
|
+
assetClass: "stable" | "volatile";
|
|
18
|
+
/** Guaranteed minimum, never discounted (Riddler). */
|
|
19
|
+
gasFloor: {
|
|
20
|
+
amount: string;
|
|
21
|
+
usd: string;
|
|
22
|
+
};
|
|
23
|
+
solverFeeBps: number;
|
|
24
|
+
solverFee: string;
|
|
25
|
+
/** > 0 only on large-vs-depth fills; render as a warning, not a fee. */
|
|
26
|
+
priceImpactBps: number;
|
|
27
|
+
priceImpact: string;
|
|
28
|
+
venueFeeBps: number;
|
|
29
|
+
venueFee: string;
|
|
30
|
+
routingFeeBps: number;
|
|
31
|
+
routingFee: string;
|
|
32
|
+
totalBps: number;
|
|
33
|
+
totalFee: string;
|
|
34
|
+
totalUsd: string;
|
|
35
|
+
/** 15 -- solver upside on positive slippage; the user keeps the other 85%. */
|
|
36
|
+
surplusSharePct: number;
|
|
37
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validators
|
|
3
|
+
*
|
|
4
|
+
* Address validators: EVM hex20 and checksummed Tron base58.
|
|
5
|
+
*/
|
|
6
|
+
/** Ethereum address regex pattern */
|
|
7
|
+
export declare const ETH_ADDRESS_REGEX: RegExp;
|
|
8
|
+
/** Zero address constant */
|
|
9
|
+
export declare const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
10
|
+
/** Check if string is a valid Ethereum address */
|
|
11
|
+
export declare function isValidAddress(address: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Tron mainnet address shape: 34 chars, leading "T", base58 alphabet (no
|
|
14
|
+
* 0/O/I/l). Shape alone is NOT sufficient to accept an address -- see
|
|
15
|
+
* `isValidTronAddress`, which also verifies the base58check checksum.
|
|
16
|
+
*/
|
|
17
|
+
export declare const TRON_ADDRESS_REGEX: RegExp;
|
|
18
|
+
/**
|
|
19
|
+
* Validate a Tron address, checksum included.
|
|
20
|
+
*
|
|
21
|
+
* The shape regex alone accepts any typo that keeps the length and alphabet,
|
|
22
|
+
* which is nearly all of them. Base58check carries a 4-byte checksum, so a
|
|
23
|
+
* mistyped address survives it with probability about 1 in 4 billion. That
|
|
24
|
+
* matters here specifically because a Tron payout recipient is typed by hand on
|
|
25
|
+
* an EVM-origin swap: there is no Tron wallet in the flow to catch it later, and
|
|
26
|
+
* a TRC-20 transfer to a well-formed but unowned address is irrecoverable.
|
|
27
|
+
*
|
|
28
|
+
* Checksum = first 4 bytes of sha256(sha256(0x41 || address_bytes)).
|
|
29
|
+
*/
|
|
30
|
+
export declare function isValidTronAddress(address: string): boolean;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validators
|
|
3
|
+
*
|
|
4
|
+
* Address validators: EVM hex20 and checksummed Tron base58.
|
|
5
|
+
*/
|
|
6
|
+
import { sha256 } from "viem";
|
|
7
|
+
// ============================================================
|
|
8
|
+
// Address Validation
|
|
9
|
+
// ============================================================
|
|
10
|
+
/** Ethereum address regex pattern */
|
|
11
|
+
export const ETH_ADDRESS_REGEX = /^0x[a-fA-F0-9]{40}$/;
|
|
12
|
+
/** Zero address constant */
|
|
13
|
+
export const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
14
|
+
/** Check if string is a valid Ethereum address */
|
|
15
|
+
export function isValidAddress(address) {
|
|
16
|
+
return ETH_ADDRESS_REGEX.test(address);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Tron mainnet address shape: 34 chars, leading "T", base58 alphabet (no
|
|
20
|
+
* 0/O/I/l). Shape alone is NOT sufficient to accept an address -- see
|
|
21
|
+
* `isValidTronAddress`, which also verifies the base58check checksum.
|
|
22
|
+
*/
|
|
23
|
+
export const TRON_ADDRESS_REGEX = /^T[1-9A-HJ-NP-Za-km-z]{33}$/;
|
|
24
|
+
const BASE58_ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
|
|
25
|
+
/** Decoded Tron address: 0x41 prefix + 20 address bytes + 4 checksum bytes. */
|
|
26
|
+
const TRON_DECODED_BYTES = 25;
|
|
27
|
+
const TRON_ADDRESS_PREFIX = 0x41;
|
|
28
|
+
/** Decode base58 into bytes. Returns null on any character outside the alphabet. */
|
|
29
|
+
function base58Decode(input) {
|
|
30
|
+
let acc = 0n;
|
|
31
|
+
for (const char of input) {
|
|
32
|
+
const digit = BASE58_ALPHABET.indexOf(char);
|
|
33
|
+
if (digit < 0)
|
|
34
|
+
return null;
|
|
35
|
+
acc = acc * 58n + BigInt(digit);
|
|
36
|
+
}
|
|
37
|
+
const bytes = [];
|
|
38
|
+
while (acc > 0n) {
|
|
39
|
+
bytes.unshift(Number(acc % 256n));
|
|
40
|
+
acc /= 256n;
|
|
41
|
+
}
|
|
42
|
+
// Every leading '1' in base58 encodes one leading zero byte.
|
|
43
|
+
for (const char of input) {
|
|
44
|
+
if (char !== BASE58_ALPHABET[0])
|
|
45
|
+
break;
|
|
46
|
+
bytes.unshift(0);
|
|
47
|
+
}
|
|
48
|
+
return Uint8Array.from(bytes);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Validate a Tron address, checksum included.
|
|
52
|
+
*
|
|
53
|
+
* The shape regex alone accepts any typo that keeps the length and alphabet,
|
|
54
|
+
* which is nearly all of them. Base58check carries a 4-byte checksum, so a
|
|
55
|
+
* mistyped address survives it with probability about 1 in 4 billion. That
|
|
56
|
+
* matters here specifically because a Tron payout recipient is typed by hand on
|
|
57
|
+
* an EVM-origin swap: there is no Tron wallet in the flow to catch it later, and
|
|
58
|
+
* a TRC-20 transfer to a well-formed but unowned address is irrecoverable.
|
|
59
|
+
*
|
|
60
|
+
* Checksum = first 4 bytes of sha256(sha256(0x41 || address_bytes)).
|
|
61
|
+
*/
|
|
62
|
+
export function isValidTronAddress(address) {
|
|
63
|
+
if (!TRON_ADDRESS_REGEX.test(address))
|
|
64
|
+
return false;
|
|
65
|
+
const decoded = base58Decode(address);
|
|
66
|
+
if (!decoded || decoded.length !== TRON_DECODED_BYTES)
|
|
67
|
+
return false;
|
|
68
|
+
if (decoded[0] !== TRON_ADDRESS_PREFIX)
|
|
69
|
+
return false;
|
|
70
|
+
const payload = decoded.subarray(0, 21);
|
|
71
|
+
const checksum = decoded.subarray(21);
|
|
72
|
+
const digest = sha256(sha256(payload, "bytes"), "bytes");
|
|
73
|
+
return checksum.every((byte, i) => byte === digest[i]);
|
|
74
|
+
}
|