@xochi/client 0.1.1 → 0.1.2

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.
@@ -0,0 +1,124 @@
1
+ /**
2
+ * Riddler's shielded terms preview wire (`POST /xochi/shielded/preview`,
3
+ * Riddler#1296): the typed request and response shapes and a decoder.
4
+ *
5
+ * There is NO transport method: the preview needs a `quote`-scoped Riddler
6
+ * credential, so only the Xochi Worker calls it, and the Worker proxy route is
7
+ * a follow-up owned by xochi#635. These shapes exist so that proxy and its
8
+ * consumers decode the solver's answer with the same schema the solver
9
+ * publishes (`packages/spec/wire/openapi.json`, `ShieldedPreviewResponse`).
10
+ *
11
+ * The preview is NOT a signing payload: `preview_digest` is the EIP-712 digest
12
+ * of `ShieldedPreviewV1` under the `Xochi Shielded Preview` domain, which no
13
+ * `ShieldedTermsV1` signature verifies against (`@xochi/spec`
14
+ * `conformance/shielded-terms.json`, PROPOSED). `executable` is always false.
15
+ */
16
+ import { z } from "zod";
17
+ import { ethAddress } from "./schemas.js";
18
+ /** 32-byte hex (`0x` + 64). */
19
+ const bytes32 = z.string().regex(/^0x[0-9a-fA-F]{64}$/);
20
+ /**
21
+ * A 32-byte Aztec address or field element. The decoder checks the shape only;
22
+ * the solver has already refused zero and values at or above the BN254 modulus.
23
+ * A 20-byte EVM address never fits.
24
+ */
25
+ export const aztecValue = bytes32;
26
+ /** Canonical unsigned decimal string (uint256 members). */
27
+ const uintString = z.string().regex(/^(0|[1-9][0-9]*)$/);
28
+ /** Canonical positive base-unit amount. */
29
+ const baseUnits = z.string().regex(/^[1-9][0-9]*$/);
30
+ export const ShieldedNetworkIdentitySchema = z.object({
31
+ aztec_chain_id: z.string().regex(/^[1-9][0-9]*$/),
32
+ protocol_version: z.string().regex(/^[1-9][0-9]*$/),
33
+ rollup_address: ethAddress,
34
+ l1_chain_id: z.string().regex(/^[1-9][0-9]*$/),
35
+ genesis_or_network_digest: bytes32,
36
+ });
37
+ export const ShieldedCorridorSchema = z.object({
38
+ corridor_id: bytes32,
39
+ revision: z.number().int().min(1).max(4294967295),
40
+ manifest_digest: bytes32,
41
+ });
42
+ export const ShieldedFeeBreakdownSchema = z.object({
43
+ gas_floor: uintString,
44
+ solver_fee_bps: z.number().int().min(0).max(10000),
45
+ solver_fee: uintString,
46
+ price_impact_bps: z.number().int().min(0).max(10000),
47
+ price_impact: uintString,
48
+ venue_fee_bps: z.number().int().min(0).max(10000),
49
+ venue_fee: uintString,
50
+ routing_fee_bps: z.number().int().min(0).max(10000),
51
+ routing_fee: uintString,
52
+ total_bps: z.number().int().min(0).max(40000),
53
+ total_fee: uintString,
54
+ });
55
+ /** `ShieldedPreviewV1` in snake_case: the terms minus the per-execution members. */
56
+ export const ShieldedPreviewSchema = z.object({
57
+ protocol_version: z.literal("xochi.shielded.preview.v1"),
58
+ environment: z.string().min(1),
59
+ source: z.object({
60
+ chain_id: z.number().int().positive(),
61
+ token_address: ethAddress,
62
+ wallet: ethAddress,
63
+ collector: ethAddress,
64
+ amount: baseUnits,
65
+ }),
66
+ destination: z.object({
67
+ settlement_type: z.literal("shielded"),
68
+ privacy_level: z.literal("private"),
69
+ disclosure_profile: z.literal("recipient-private-public-amount-v1"),
70
+ rail: z.literal("a_tracer"),
71
+ network: ShieldedNetworkIdentitySchema,
72
+ corridor: ShieldedCorridorSchema,
73
+ asset_id: z.string().min(1),
74
+ token_address: aztecValue,
75
+ recipient_binding_id: z.string().min(1),
76
+ recipient_descriptor_digest: bytes32,
77
+ recipient_address: aztecValue,
78
+ amount: baseUnits,
79
+ fee_payer: aztecValue,
80
+ }),
81
+ fee_breakdown: ShieldedFeeBreakdownSchema,
82
+ refund_address: ethAddress,
83
+ refund_amount: baseUnits,
84
+ collect_before: z.number().int().nonnegative(),
85
+ settlement_service_deadline: z.number().int().nonnegative(),
86
+ recipient_binding_digest: bytes32,
87
+ policy_revision: z.number().int().nonnegative(),
88
+ });
89
+ export const ShieldedPreviewResponseSchema = z.object({
90
+ executable: z.literal(false),
91
+ preview_version: z.literal("xochi.shielded.preview.v1"),
92
+ preview_digest: bytes32,
93
+ recipient_binding_digest: bytes32,
94
+ domain: z.object({
95
+ name: z.literal("Xochi Shielded Preview"),
96
+ version: z.literal("1"),
97
+ chain_id: z.number().int().positive(),
98
+ salt: bytes32,
99
+ }),
100
+ preview: ShieldedPreviewSchema,
101
+ manifest: z.object({
102
+ manifest_digest: bytes32,
103
+ aztec_sdk_version: z.string().min(1),
104
+ recipient_account_class_id: aztecValue,
105
+ }),
106
+ });
107
+ /**
108
+ * Decode a preview response. Throws (zod) on any shape the solver does not
109
+ * publish, including an executable or terms-shaped answer, and on a fee
110
+ * breakdown whose totals disagree: `total_fee` must be `max(gas_floor, layers)` (the gas
111
+ * floor is a minimum fee, as in FeePolicy) and `total_bps` the four rates.
112
+ */
113
+ export function decodeShieldedPreview(body) {
114
+ const decoded = ShieldedPreviewResponseSchema.parse(body);
115
+ const f = decoded.preview.fee_breakdown;
116
+ const layers = BigInt(f.solver_fee) + BigInt(f.price_impact) + BigInt(f.venue_fee) + BigInt(f.routing_fee);
117
+ const gasFloor = BigInt(f.gas_floor);
118
+ const totalFee = layers > gasFloor ? layers : gasFloor;
119
+ const totalBps = f.solver_fee_bps + f.price_impact_bps + f.venue_fee_bps + f.routing_fee_bps;
120
+ if (BigInt(f.total_fee) !== totalFee || f.total_bps !== totalBps) {
121
+ throw new Error("shielded preview fee_breakdown totals disagree with max(gas_floor, layers)");
122
+ }
123
+ return decoded;
124
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xochi/client",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Xochi trade API client: transport, trade state machine, pre-sign fund-safety checks.",
5
5
  "keywords": [
6
6
  "xochi",