@nullclear/x402-arbiter 0.0.0-stage → 1.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/LICENSE +21 -0
- package/README.md +36 -2
- package/dist/index.cjs +328 -0
- package/dist/index.d.cts +129 -0
- package/dist/index.d.mts +104 -0
- package/dist/index.d.ts +129 -0
- package/dist/index.js +303 -0
- package/dist/index.mjs +295 -0
- package/package.json +43 -3
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { PrivateKeyAccount } from 'viem/accounts';
|
|
2
|
+
import { WalletClient } from 'viem';
|
|
3
|
+
import { X402PaymentOption, ValidationConfig, FallbackTarget, SpendPolicy, KYAMandate, InvariantRule } from '@nullclear/shared';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
|
|
6
|
+
type SignerInput = `0x${string}` | PrivateKeyAccount | {
|
|
7
|
+
account: {
|
|
8
|
+
address: `0x${string}`;
|
|
9
|
+
};
|
|
10
|
+
signTypedData: (params: any) => Promise<`0x${string}`>;
|
|
11
|
+
} | WalletClient;
|
|
12
|
+
/**
|
|
13
|
+
* Signs an EIP-3009 TransferWithAuthorization and returns a Base64 encoded X402PaymentSignaturePayload
|
|
14
|
+
*/
|
|
15
|
+
declare function signX402Payment(signer: SignerInput, option: X402PaymentOption, resourceUrl?: string): Promise<string>;
|
|
16
|
+
|
|
17
|
+
interface NullClearClientConfig {
|
|
18
|
+
arbiterUrl?: string;
|
|
19
|
+
defaultChainId?: number;
|
|
20
|
+
fetch?: typeof fetch;
|
|
21
|
+
}
|
|
22
|
+
interface ClearRequest {
|
|
23
|
+
targetUrl: string;
|
|
24
|
+
method?: "GET" | "POST" | "PUT" | "DELETE";
|
|
25
|
+
headers?: Record<string, string>;
|
|
26
|
+
body?: unknown;
|
|
27
|
+
paymentSignatureHeader: string;
|
|
28
|
+
sellerAgentId?: string;
|
|
29
|
+
minTrustScore?: number;
|
|
30
|
+
twoPhaseRelease?: boolean;
|
|
31
|
+
validation?: ValidationConfig;
|
|
32
|
+
fallbacks?: FallbackTarget[];
|
|
33
|
+
spendPolicy?: SpendPolicy;
|
|
34
|
+
}
|
|
35
|
+
interface ClearResult<T = unknown> {
|
|
36
|
+
cleared: boolean;
|
|
37
|
+
settled: boolean;
|
|
38
|
+
clearingId?: string;
|
|
39
|
+
buyerCharged: string;
|
|
40
|
+
clearingFee?: string;
|
|
41
|
+
settlementRouting?: string;
|
|
42
|
+
transaction?: `0x${string}`;
|
|
43
|
+
attestation?: unknown;
|
|
44
|
+
data?: T;
|
|
45
|
+
stage?: string;
|
|
46
|
+
error?: string;
|
|
47
|
+
validationErrors?: string[];
|
|
48
|
+
failoverAttempts?: number;
|
|
49
|
+
winningSellerAgentId?: string;
|
|
50
|
+
failedCandidates?: Array<{
|
|
51
|
+
targetUrl: string;
|
|
52
|
+
sellerAgentId?: string;
|
|
53
|
+
stage: string;
|
|
54
|
+
reason: string;
|
|
55
|
+
}>;
|
|
56
|
+
}
|
|
57
|
+
declare class NullClearClient {
|
|
58
|
+
private arbiterUrl;
|
|
59
|
+
private defaultChainId;
|
|
60
|
+
private customFetch;
|
|
61
|
+
constructor(config?: NullClearClientConfig);
|
|
62
|
+
getScore(agentId: string, chainId?: number): Promise<any>;
|
|
63
|
+
clear<T = unknown>(request: ClearRequest): Promise<ClearResult<T>>;
|
|
64
|
+
getKya(agentId: string, chainId?: number): Promise<any>;
|
|
65
|
+
attestKya(mandate: KYAMandate, chainId?: number, signature?: string, signerAddress?: `0x${string}`): Promise<any>;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
declare class NullClearEscrowAbortedError extends Error {
|
|
69
|
+
stage: string;
|
|
70
|
+
buyerCharged: string;
|
|
71
|
+
validationErrors: string[];
|
|
72
|
+
score?: number;
|
|
73
|
+
upstreamStatus?: number;
|
|
74
|
+
reason?: string;
|
|
75
|
+
failoverAttempts?: number;
|
|
76
|
+
failedCandidates?: Array<{
|
|
77
|
+
targetUrl: string;
|
|
78
|
+
sellerAgentId?: string;
|
|
79
|
+
stage: string;
|
|
80
|
+
reason: string;
|
|
81
|
+
}>;
|
|
82
|
+
constructor(message: string, details: {
|
|
83
|
+
stage: string;
|
|
84
|
+
buyerCharged?: string;
|
|
85
|
+
validationErrors?: string[];
|
|
86
|
+
score?: number;
|
|
87
|
+
upstreamStatus?: number;
|
|
88
|
+
reason?: string;
|
|
89
|
+
failoverAttempts?: number;
|
|
90
|
+
failedCandidates?: Array<{
|
|
91
|
+
targetUrl: string;
|
|
92
|
+
sellerAgentId?: string;
|
|
93
|
+
stage: string;
|
|
94
|
+
reason: string;
|
|
95
|
+
}>;
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Lightweight deterministic Zod-to-JSON-Schema converter
|
|
100
|
+
*/
|
|
101
|
+
declare function zodToJsonSchema(schema: z.ZodTypeAny): Record<string, unknown>;
|
|
102
|
+
interface NullClearOptions {
|
|
103
|
+
sellerAgentId?: string;
|
|
104
|
+
minTrustScore?: number;
|
|
105
|
+
schema?: z.ZodTypeAny | Record<string, unknown>;
|
|
106
|
+
requiredFields?: string[];
|
|
107
|
+
sha256Match?: string;
|
|
108
|
+
invariants?: InvariantRule[];
|
|
109
|
+
rejectRefusals?: boolean;
|
|
110
|
+
fallbacks?: FallbackTarget[];
|
|
111
|
+
spendPolicy?: SpendPolicy;
|
|
112
|
+
}
|
|
113
|
+
interface NullClearFetchConfig {
|
|
114
|
+
accountOrPrivateKey: SignerInput;
|
|
115
|
+
chainId?: number;
|
|
116
|
+
arbiterUrl?: string;
|
|
117
|
+
defaultMinTrustScore?: number;
|
|
118
|
+
customFetch?: typeof fetch;
|
|
119
|
+
}
|
|
120
|
+
type NullClearRequestInit = RequestInit & {
|
|
121
|
+
nullclear?: NullClearOptions;
|
|
122
|
+
};
|
|
123
|
+
/**
|
|
124
|
+
* Creates an enhanced fetch client that autonomously intercepts HTTP 402 Payment Required
|
|
125
|
+
* and safely wraps the call in NullClear Deferred Non-Custodial Schema Escrow
|
|
126
|
+
*/
|
|
127
|
+
declare function createNullClearFetch(config: NullClearFetchConfig): (input: RequestInfo | URL, init?: NullClearRequestInit) => Promise<Response>;
|
|
128
|
+
|
|
129
|
+
export { type ClearRequest, type ClearResult, NullClearClient, type NullClearClientConfig, NullClearEscrowAbortedError, type NullClearFetchConfig, type NullClearOptions, type NullClearRequestInit, type SignerInput, createNullClearFetch, signX402Payment, zodToJsonSchema };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,303 @@
|
|
|
1
|
+
// src/signer.ts
|
|
2
|
+
import { privateKeyToAccount } from "viem/accounts";
|
|
3
|
+
import {
|
|
4
|
+
EIP3009_TYPES,
|
|
5
|
+
getChainConfig,
|
|
6
|
+
encodeBase64Json
|
|
7
|
+
} from "@nullclear/shared";
|
|
8
|
+
async function signX402Payment(signer, option, resourceUrl) {
|
|
9
|
+
let accountAddress;
|
|
10
|
+
let signTypedDataFn;
|
|
11
|
+
if (typeof signer === "string" && signer.startsWith("0x")) {
|
|
12
|
+
const account = privateKeyToAccount(signer);
|
|
13
|
+
accountAddress = account.address;
|
|
14
|
+
signTypedDataFn = (params) => account.signTypedData(params);
|
|
15
|
+
} else if (typeof signer === "object" && signer !== null && "signTypedData" in signer && "account" in signer && signer.account) {
|
|
16
|
+
const rawAccount = signer.account;
|
|
17
|
+
accountAddress = typeof rawAccount === "string" ? rawAccount : rawAccount.address;
|
|
18
|
+
signTypedDataFn = (params) => signer.signTypedData(params);
|
|
19
|
+
} else {
|
|
20
|
+
throw new Error("Invalid signer provided to signX402Payment: must be private key or viem account/wallet client");
|
|
21
|
+
}
|
|
22
|
+
const randomBytes = new Uint8Array(32);
|
|
23
|
+
crypto.getRandomValues(randomBytes);
|
|
24
|
+
const nonce = `0x` + Array.from(randomBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
25
|
+
const validAfter = "0";
|
|
26
|
+
const timeoutSeconds = option.maxTimeoutSeconds && option.maxTimeoutSeconds > 0 ? option.maxTimeoutSeconds : 300;
|
|
27
|
+
const validBefore = String(Math.floor(Date.now() / 1e3) + timeoutSeconds);
|
|
28
|
+
const chainConfig = getChainConfig(option.network);
|
|
29
|
+
const domain = {
|
|
30
|
+
name: chainConfig.usdcDomain.name,
|
|
31
|
+
version: chainConfig.usdcDomain.version,
|
|
32
|
+
chainId: chainConfig.chainId,
|
|
33
|
+
verifyingContract: chainConfig.usdc
|
|
34
|
+
};
|
|
35
|
+
const authorization = {
|
|
36
|
+
from: accountAddress,
|
|
37
|
+
to: option.payTo,
|
|
38
|
+
value: option.amount,
|
|
39
|
+
validAfter,
|
|
40
|
+
validBefore,
|
|
41
|
+
nonce
|
|
42
|
+
};
|
|
43
|
+
const signature = await signTypedDataFn({
|
|
44
|
+
domain,
|
|
45
|
+
types: EIP3009_TYPES,
|
|
46
|
+
primaryType: "TransferWithAuthorization",
|
|
47
|
+
message: {
|
|
48
|
+
from: authorization.from,
|
|
49
|
+
to: authorization.to,
|
|
50
|
+
value: BigInt(authorization.value),
|
|
51
|
+
validAfter: BigInt(authorization.validAfter),
|
|
52
|
+
validBefore: BigInt(authorization.validBefore),
|
|
53
|
+
nonce: authorization.nonce
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
const payload = {
|
|
57
|
+
x402Version: 2,
|
|
58
|
+
resource: resourceUrl ? { url: resourceUrl } : void 0,
|
|
59
|
+
accepted: option,
|
|
60
|
+
payload: {
|
|
61
|
+
signature,
|
|
62
|
+
authorization
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
return encodeBase64Json(payload);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// src/client.ts
|
|
69
|
+
var NullClearClient = class {
|
|
70
|
+
arbiterUrl;
|
|
71
|
+
defaultChainId;
|
|
72
|
+
customFetch;
|
|
73
|
+
constructor(config = {}) {
|
|
74
|
+
this.arbiterUrl = (config.arbiterUrl || "https://arbiter.nullclear.dev").replace(/\/$/, "");
|
|
75
|
+
this.defaultChainId = config.defaultChainId || 8453;
|
|
76
|
+
this.customFetch = config.fetch || fetch;
|
|
77
|
+
}
|
|
78
|
+
async getScore(agentId, chainId) {
|
|
79
|
+
const targetChainId = chainId || this.defaultChainId;
|
|
80
|
+
const res = await this.customFetch(`${this.arbiterUrl}/v1/score/${targetChainId}/${agentId}`);
|
|
81
|
+
if (!res.ok) {
|
|
82
|
+
const err = await res.text();
|
|
83
|
+
throw new Error(`Failed to fetch score for agent ${agentId}: ${res.status} ${err}`);
|
|
84
|
+
}
|
|
85
|
+
const data = await res.json();
|
|
86
|
+
return data.data;
|
|
87
|
+
}
|
|
88
|
+
async clear(request) {
|
|
89
|
+
const res = await this.customFetch(`${this.arbiterUrl}/v1/clear`, {
|
|
90
|
+
method: "POST",
|
|
91
|
+
headers: { "Content-Type": "application/json" },
|
|
92
|
+
body: JSON.stringify(request)
|
|
93
|
+
});
|
|
94
|
+
const data = await res.json();
|
|
95
|
+
return data;
|
|
96
|
+
}
|
|
97
|
+
async getKya(agentId, chainId) {
|
|
98
|
+
const targetChainId = chainId || this.defaultChainId;
|
|
99
|
+
const res = await this.customFetch(`${this.arbiterUrl}/v1/kya/${targetChainId}/${agentId}`);
|
|
100
|
+
if (!res.ok) {
|
|
101
|
+
if (res.status === 404) return null;
|
|
102
|
+
const err = await res.text();
|
|
103
|
+
throw new Error(`Failed to fetch KYA mandate for agent ${agentId}: ${res.status} ${err}`);
|
|
104
|
+
}
|
|
105
|
+
const data = await res.json();
|
|
106
|
+
return data.data;
|
|
107
|
+
}
|
|
108
|
+
async attestKya(mandate, chainId, signature, signerAddress) {
|
|
109
|
+
const targetChainId = chainId || this.defaultChainId;
|
|
110
|
+
const res = await this.customFetch(`${this.arbiterUrl}/v1/kya/attest`, {
|
|
111
|
+
method: "POST",
|
|
112
|
+
headers: { "Content-Type": "application/json" },
|
|
113
|
+
body: JSON.stringify({
|
|
114
|
+
mandate,
|
|
115
|
+
chainId: targetChainId,
|
|
116
|
+
signature,
|
|
117
|
+
signerAddress
|
|
118
|
+
})
|
|
119
|
+
});
|
|
120
|
+
if (!res.ok) {
|
|
121
|
+
const err = await res.text();
|
|
122
|
+
throw new Error(`Failed to attest KYA mandate: ${res.status} ${err}`);
|
|
123
|
+
}
|
|
124
|
+
const data = await res.json();
|
|
125
|
+
return data.data;
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// src/fetch-wrapper.ts
|
|
130
|
+
import { z } from "zod";
|
|
131
|
+
import {
|
|
132
|
+
decodeBase64Json
|
|
133
|
+
} from "@nullclear/shared";
|
|
134
|
+
var NullClearEscrowAbortedError = class extends Error {
|
|
135
|
+
stage;
|
|
136
|
+
buyerCharged;
|
|
137
|
+
validationErrors;
|
|
138
|
+
score;
|
|
139
|
+
upstreamStatus;
|
|
140
|
+
reason;
|
|
141
|
+
failoverAttempts;
|
|
142
|
+
failedCandidates;
|
|
143
|
+
constructor(message, details) {
|
|
144
|
+
super(message);
|
|
145
|
+
this.name = "NullClearEscrowAbortedError";
|
|
146
|
+
this.stage = details.stage;
|
|
147
|
+
this.buyerCharged = details.buyerCharged || "0";
|
|
148
|
+
this.validationErrors = details.validationErrors || [];
|
|
149
|
+
this.score = details.score;
|
|
150
|
+
this.upstreamStatus = details.upstreamStatus;
|
|
151
|
+
this.reason = details.reason;
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
function zodToJsonSchema(schema) {
|
|
155
|
+
const def = schema._def;
|
|
156
|
+
if (!def) return {};
|
|
157
|
+
const typeName = def.typeName;
|
|
158
|
+
switch (typeName) {
|
|
159
|
+
case "ZodString":
|
|
160
|
+
return { type: "string" };
|
|
161
|
+
case "ZodNumber":
|
|
162
|
+
return { type: "number" };
|
|
163
|
+
case "ZodBoolean":
|
|
164
|
+
return { type: "boolean" };
|
|
165
|
+
case "ZodArray":
|
|
166
|
+
return {
|
|
167
|
+
type: "array",
|
|
168
|
+
items: def.type ? zodToJsonSchema(def.type) : {}
|
|
169
|
+
};
|
|
170
|
+
case "ZodObject": {
|
|
171
|
+
const shape = def.shape();
|
|
172
|
+
const properties = {};
|
|
173
|
+
const required = [];
|
|
174
|
+
for (const [key, value] of Object.entries(shape)) {
|
|
175
|
+
properties[key] = zodToJsonSchema(value);
|
|
176
|
+
const subDef = value._def;
|
|
177
|
+
if (subDef.typeName !== "ZodOptional" && subDef.typeName !== "ZodNullable") {
|
|
178
|
+
required.push(key);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
type: "object",
|
|
183
|
+
properties,
|
|
184
|
+
required: required.length > 0 ? required : void 0
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
case "ZodEnum":
|
|
188
|
+
return {
|
|
189
|
+
type: "string",
|
|
190
|
+
enum: def.values
|
|
191
|
+
};
|
|
192
|
+
case "ZodOptional":
|
|
193
|
+
case "ZodNullable":
|
|
194
|
+
return def.innerType ? zodToJsonSchema(def.innerType) : {};
|
|
195
|
+
default:
|
|
196
|
+
return {};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function createNullClearFetch(config) {
|
|
200
|
+
const chainId = config.chainId || 8453;
|
|
201
|
+
const arbiterUrl = (config.arbiterUrl || "https://arbiter.nullclear.dev").replace(/\/$/, "");
|
|
202
|
+
const defaultMinTrustScore = config.defaultMinTrustScore || 50;
|
|
203
|
+
const customFetch = config.customFetch || fetch;
|
|
204
|
+
return async function nullclearFetch(input, init) {
|
|
205
|
+
const targetUrl = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
206
|
+
const fetchInit = { ...init };
|
|
207
|
+
delete fetchInit.nullclear;
|
|
208
|
+
const initialRes = await customFetch(input, fetchInit);
|
|
209
|
+
if (initialRes.status !== 402) {
|
|
210
|
+
return initialRes;
|
|
211
|
+
}
|
|
212
|
+
const paymentRequiredHeader = initialRes.headers.get("PAYMENT-REQUIRED") || initialRes.headers.get("payment-required");
|
|
213
|
+
if (!paymentRequiredHeader) {
|
|
214
|
+
return initialRes;
|
|
215
|
+
}
|
|
216
|
+
let paymentRequired;
|
|
217
|
+
try {
|
|
218
|
+
paymentRequired = decodeBase64Json(paymentRequiredHeader);
|
|
219
|
+
} catch {
|
|
220
|
+
return initialRes;
|
|
221
|
+
}
|
|
222
|
+
const targetNetwork = `eip155:${chainId}`;
|
|
223
|
+
const selectedOption = paymentRequired.accepts.find(
|
|
224
|
+
(opt) => opt.network === targetNetwork && opt.scheme === "exact"
|
|
225
|
+
);
|
|
226
|
+
if (!selectedOption) {
|
|
227
|
+
throw new Error(
|
|
228
|
+
`Seller does not accept payments on network ${targetNetwork}. Accepted: ${paymentRequired.accepts.map((a) => a.network).join(", ")}`
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
const paymentSignatureHeader = await signX402Payment(
|
|
232
|
+
config.accountOrPrivateKey,
|
|
233
|
+
selectedOption,
|
|
234
|
+
targetUrl
|
|
235
|
+
);
|
|
236
|
+
let jsonSchema;
|
|
237
|
+
if (init?.nullclear?.schema) {
|
|
238
|
+
if (init.nullclear.schema instanceof z.ZodType) {
|
|
239
|
+
jsonSchema = zodToJsonSchema(init.nullclear.schema);
|
|
240
|
+
} else if (typeof init.nullclear.schema === "object") {
|
|
241
|
+
jsonSchema = init.nullclear.schema;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
const clearPayload = {
|
|
245
|
+
targetUrl,
|
|
246
|
+
method: init?.method || "GET",
|
|
247
|
+
headers: init?.headers || {},
|
|
248
|
+
body: init?.body,
|
|
249
|
+
paymentSignatureHeader,
|
|
250
|
+
sellerAgentId: init?.nullclear?.sellerAgentId,
|
|
251
|
+
minTrustScore: init?.nullclear?.minTrustScore ?? defaultMinTrustScore,
|
|
252
|
+
validation: {
|
|
253
|
+
expectedStatus: [200],
|
|
254
|
+
jsonSchema,
|
|
255
|
+
requiredFields: init?.nullclear?.requiredFields,
|
|
256
|
+
sha256Match: init?.nullclear?.sha256Match,
|
|
257
|
+
rejectRefusals: init?.nullclear?.rejectRefusals ?? true,
|
|
258
|
+
invariants: init?.nullclear?.invariants
|
|
259
|
+
},
|
|
260
|
+
fallbacks: init?.nullclear?.fallbacks,
|
|
261
|
+
spendPolicy: init?.nullclear?.spendPolicy
|
|
262
|
+
};
|
|
263
|
+
const arbiterRes = await customFetch(`${arbiterUrl}/v1/clear`, {
|
|
264
|
+
method: "POST",
|
|
265
|
+
headers: { "Content-Type": "application/json" },
|
|
266
|
+
body: JSON.stringify(clearPayload)
|
|
267
|
+
});
|
|
268
|
+
const arbiterData = await arbiterRes.json();
|
|
269
|
+
if (arbiterRes.status === 200 && arbiterData.cleared) {
|
|
270
|
+
const resBody = typeof arbiterData.data === "string" ? arbiterData.data : JSON.stringify(arbiterData.data);
|
|
271
|
+
const resHeaders = new Headers();
|
|
272
|
+
resHeaders.set("Content-Type", "application/json");
|
|
273
|
+
const paymentResponseHdr = arbiterRes.headers.get("PAYMENT-RESPONSE");
|
|
274
|
+
if (paymentResponseHdr) resHeaders.set("PAYMENT-RESPONSE", paymentResponseHdr);
|
|
275
|
+
const attestationHdr = arbiterRes.headers.get("X-NullClear-Attestation");
|
|
276
|
+
if (attestationHdr) resHeaders.set("X-NullClear-Attestation", attestationHdr);
|
|
277
|
+
return new Response(resBody, {
|
|
278
|
+
status: 200,
|
|
279
|
+
headers: resHeaders
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
throw new NullClearEscrowAbortedError(
|
|
283
|
+
`NullClear Escrow Aborted: ${arbiterData.stage || "FAILED"} - ${arbiterData.reason || arbiterData.error || (arbiterData.validationErrors || []).join("; ")}`,
|
|
284
|
+
{
|
|
285
|
+
stage: arbiterData.stage || "UNKNOWN_FAILURE",
|
|
286
|
+
buyerCharged: arbiterData.buyerCharged || "0",
|
|
287
|
+
validationErrors: arbiterData.validationErrors || [],
|
|
288
|
+
score: arbiterData.score,
|
|
289
|
+
upstreamStatus: arbiterData.upstreamStatus,
|
|
290
|
+
reason: arbiterData.reason || arbiterData.error,
|
|
291
|
+
failoverAttempts: arbiterData.failoverAttempts,
|
|
292
|
+
failedCandidates: arbiterData.failedCandidates
|
|
293
|
+
}
|
|
294
|
+
);
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
export {
|
|
298
|
+
NullClearClient,
|
|
299
|
+
NullClearEscrowAbortedError,
|
|
300
|
+
createNullClearFetch,
|
|
301
|
+
signX402Payment,
|
|
302
|
+
zodToJsonSchema
|
|
303
|
+
};
|