@opendatalabs/vana-sdk 4.0.0 → 4.2.0

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.
@@ -32117,15 +32117,14 @@ var PREIMAGE_SEPARATOR = ":";
32117
32117
  var UNCOMPRESSED_PUBLIC_KEY_BYTES = 65;
32118
32118
  var UNCOMPRESSED_PUBLIC_KEY_PREFIX = "04";
32119
32119
  var EMPTY_HEX = "0x";
32120
- function emptyAnchor() {
32121
- return Object.freeze({
32122
- kmsRootPubkey: EMPTY_HEX,
32123
- appIds: Object.freeze([])
32124
- });
32125
- }
32120
+ var MAINNET_ANCHOR = Object.freeze({
32121
+ kmsRootPubkey: "0x0434c76e0c3f52ec64cbf9bbf5c910c272330166fd656c0a86bb330963e46910e1a0e6fa51bec74be2f9129342707636060d85856d102cee8290185409ecf7422f",
32122
+ appIds: Object.freeze([
32123
+ "0x01bb1b6dcaf1ea170f1480c5e53b093f384d939a"
32124
+ ])
32125
+ });
32126
32126
  var ENCLAVE_TRUST_ANCHORS = Object.freeze({
32127
- // filled at fleet provisioning; verify fails closed while empty
32128
- [VANA_MAINNET_CHAIN_ID]: emptyAnchor(),
32127
+ [VANA_MAINNET_CHAIN_ID]: MAINNET_ANCHOR,
32129
32128
  // Moksha workers share this dstack app and KMS root; the controller does not derive owner keys.
32130
32129
  [MOKSHA_CHAIN_ID]: Object.freeze({
32131
32130
  kmsRootPubkey: "0x0434c76e0c3f52ec64cbf9bbf5c910c272330166fd656c0a86bb330963e46910e1a0e6fa51bec74be2f9129342707636060d85856d102cee8290185409ecf7422f",
@@ -32289,7 +32288,9 @@ import {
32289
32288
  bytesToHex as bytesToHex3,
32290
32289
  isAddress as isAddress2,
32291
32290
  isAddressEqual as isAddressEqual2,
32292
- isHex as isHex2
32291
+ isHex as isHex3,
32292
+ keccak256 as keccak2562,
32293
+ toHex as toHex9
32293
32294
  } from "viem";
32294
32295
  import { privateKeyToAccount, publicKeyToAddress as publicKeyToAddress2 } from "viem/accounts";
32295
32296
 
@@ -33078,208 +33079,731 @@ import {
33078
33079
  JobTransportError,
33079
33080
  OwnerNotReadyError
33080
33081
  } from "./errors.js";
33082
+ import { PaymentRequiredError } from "./direct/errors.js";
33081
33083
 
33082
- // src/protocol/write-signer.ts
33083
- import { WriteRequestError } from "./errors.js";
33084
- function isRecord(value) {
33085
- return value !== null && typeof value === "object";
33086
- }
33087
- function isViemWriteAccount(source) {
33088
- return isRecord(source) && source.type === "local" && typeof source.address === "string" && typeof source.signMessage === "function";
33089
- }
33090
- function isViemWriteWalletClient(source) {
33091
- return isRecord(source) && typeof source.signMessage === "function" && source.type !== "local" && (source.type === "walletClient" || "transport" in source);
33092
- }
33093
- function accountAddress(account) {
33094
- return typeof account === "string" ? account : account.address;
33095
- }
33096
- function resolveWriteSigner(source, options = {}) {
33097
- if (isViemWriteWalletClient(source)) {
33098
- const account = options.account ?? source.account;
33099
- if (account === void 0) {
33100
- throw new WriteRequestError(
33101
- "Viem wallet client requires an account option or account property"
33102
- );
33084
+ // src/config/contracts.config.ts
33085
+ var CONTRACTS2 = {
33086
+ // ========================================
33087
+ // DATA PORTABILITY CONTRACTS
33088
+ // ========================================
33089
+ DataPortabilityEscrow: {
33090
+ addresses: {
33091
+ 14800: "0x07d7769081adc3a3DBe91f5E4B98E9A5a6B292e3",
33092
+ 1480: "0x07d7769081adc3a3DBe91f5E4B98E9A5a6B292e3"
33103
33093
  }
33104
- return {
33105
- address: accountAddress(account),
33106
- signMessage: (message) => source.signMessage({ account, message })
33107
- };
33108
- }
33109
- if (isViemWriteAccount(source)) {
33110
- return {
33111
- address: source.address,
33112
- signMessage: (message) => source.signMessage({ message })
33113
- };
33114
- }
33115
- if (!isRecord(source) || typeof source.signMessage !== "function") {
33116
- throw new WriteRequestError(
33117
- "signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object"
33118
- );
33119
- }
33120
- return source;
33121
- }
33122
-
33123
- // src/protocol/jobs-client.ts
33124
- var IDENTITY_PATH = "/v1/identity";
33125
- var JOBS_PATH = "/v1/jobs";
33126
- var JOB_EXECUTE_PATH = "/v1/jobs/execute";
33127
- var AUTHORIZATION_HEADER = "Authorization";
33128
- var CONTENT_TYPE_HEADER = "Content-Type";
33129
- var JSON_CONTENT_TYPE = "application/json";
33130
- var GET_METHOD = "GET";
33131
- var POST_METHOD = "POST";
33132
- var RAW_READ_OPERATION = "raw_read";
33133
- var SEALED_IDENTITY_STATE = "sealed";
33134
- var HTTP_OK = 200;
33135
- var HTTP_ACCEPTED = 202;
33136
- var HTTP_UNAUTHORIZED = 401;
33137
- var HTTP_FORBIDDEN = 403;
33138
- var HTTP_NOT_FOUND = 404;
33139
- var HTTP_CONFLICT = 409;
33140
- var HTTP_PAYLOAD_TOO_LARGE = 413;
33141
- var MILLISECONDS_PER_SECOND = 1e3;
33142
- var DEFAULT_JOB_TIMEOUT_MS = 12e4;
33143
- var DEFAULT_JOB_POLL_MS = CLAIM_POLL_FLOOR_MS;
33144
- var TERMINAL_JOB_STATES = /* @__PURE__ */ new Set([
33145
- "completed",
33146
- "failed",
33147
- "expired",
33148
- "cancelled"
33149
- ]);
33150
- function isRecord2(value) {
33151
- return value !== null && typeof value === "object" && !Array.isArray(value);
33152
- }
33153
- function normalizeGateway(gatewayUrl) {
33154
- try {
33155
- const url = new URL(gatewayUrl);
33156
- if (url.pathname !== "/" || url.search !== "" || url.hash !== "") {
33157
- throw new JobRejectedError(
33158
- "gatewayUrl must be an origin without a path, query, or fragment"
33159
- );
33094
+ },
33095
+ FeeRegistry: {
33096
+ addresses: {
33097
+ 14800: "0xb4FA18443E0FA6cdC0280D20b8cCDB2377D13Bf2",
33098
+ 1480: "0xb4FA18443E0FA6cdC0280D20b8cCDB2377D13Bf2"
33160
33099
  }
33161
- return {
33162
- baseUrl: url.origin,
33163
- audience: url.origin
33164
- };
33165
- } catch (error) {
33166
- if (error instanceof JobRejectedError) throw error;
33167
- throw new JobRejectedError(
33168
- "gatewayUrl must be an absolute URL",
33169
- void 0,
33170
- null,
33171
- {
33172
- cause: error instanceof Error ? error.message : String(error)
33173
- }
33174
- );
33175
- }
33176
- }
33177
- function resolveFetch(fetchFn) {
33178
- const resolved = fetchFn ?? globalThis.fetch;
33179
- if (resolved === void 0) {
33180
- throw new JobRejectedError("No fetch implementation available");
33181
- }
33182
- return resolved;
33183
- }
33184
- function sourcePublicKey(source) {
33185
- if (isRecord2(source) && typeof source["publicKey"] === "string") {
33186
- return source["publicKey"];
33187
- }
33188
- return void 0;
33189
- }
33190
- function resolveBuilder(options) {
33191
- if (options.builderPrivateKey && options.builderAccount) {
33192
- throw new JobRejectedError(
33193
- "Provide builderPrivateKey or builderAccount, not both"
33194
- );
33195
- }
33196
- let source;
33197
- try {
33198
- source = options.builderPrivateKey ? privateKeyToAccount(options.builderPrivateKey) : options.builderAccount;
33199
- } catch (error) {
33200
- throw new JobRejectedError("Invalid builder private key", void 0, null, {
33201
- cause: error instanceof Error ? error.message : String(error)
33202
- });
33203
- }
33204
- if (!source) {
33205
- throw new JobRejectedError(
33206
- "builderPrivateKey or builderAccount is required"
33207
- );
33208
- }
33209
- let signer;
33210
- try {
33211
- signer = resolveWriteSigner(source);
33212
- } catch (error) {
33213
- throw new JobRejectedError("Invalid builder signer", void 0, null, {
33214
- cause: error instanceof Error ? error.message : String(error)
33215
- });
33216
- }
33217
- const publicKey = sourcePublicKey(source);
33218
- if (!signer.address || !publicKey) {
33219
- throw new JobRejectedError(
33220
- "Builder signer must expose both address and publicKey"
33221
- );
33222
- }
33223
- return {
33224
- builder: {
33225
- address: signer.address,
33226
- publicKey,
33227
- signMessage: signer.signMessage
33100
+ },
33101
+ // V2 deployment (DataPortabilityPermissionsV2Proxy). The gateway is the source
33102
+ // of truth for which deployment is live; verify with
33103
+ // `cast call <address> "eip712Domain()(bytes1,string,string,uint256,address,bytes32,uint256[])"`
33104
+ // which must return the domain name "Vana Data Portability".
33105
+ DataPortabilityPermissions: {
33106
+ addresses: {
33107
+ 14800: "0x4d3FA76064D88e0454cFc4CaD7e5FeC3e3124011",
33108
+ 1480: "0x4d3FA76064D88e0454cFc4CaD7e5FeC3e3124011"
33109
+ }
33110
+ },
33111
+ // V2 deployment (DataPortabilityServersV2Proxy) on both chains.
33112
+ DataPortabilityServers: {
33113
+ addresses: {
33114
+ 14800: "0xCae2CE0e9caa6643ed28186cF57bd40Bd9E17Eab",
33115
+ 1480: "0xCae2CE0e9caa6643ed28186cF57bd40Bd9E17Eab"
33116
+ }
33117
+ },
33118
+ DataPortabilityGrantees: {
33119
+ addresses: {
33120
+ 14800: "0x8325C0A0948483EdA023A1A2Fd895e62C5131234",
33121
+ 1480: "0x8325C0A0948483EdA023A1A2Fd895e62C5131234"
33122
+ }
33123
+ },
33124
+ DataRegistry: {
33125
+ addresses: {
33126
+ 14800: "0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C",
33127
+ 1480: "0x8C8788f98385F6ba1adD4234e551ABba0f82Cb7C"
33128
+ }
33129
+ },
33130
+ // ========================================
33131
+ // COMPUTING INFRASTRUCTURE
33132
+ // ========================================
33133
+ ComputeEngine: {
33134
+ addresses: {
33135
+ 14800: "0xb2BFe33FA420c45F1Cf1287542ad81ae935447bd",
33136
+ 1480: "0xb2BFe33FA420c45F1Cf1287542ad81ae935447bd"
33137
+ }
33138
+ },
33139
+ ComputeEngineTreasury: {
33140
+ addresses: {
33141
+ 14800: "0xceB33C501B624D984bD1Ed3298f6D1d8F7CE03d1",
33142
+ 1480: "0xceB33C501B624D984bD1Ed3298f6D1d8F7CE03d1"
33228
33143
  },
33229
- ...options.builderPrivateKey ? { privateKey: options.builderPrivateKey } : {}
33230
- };
33231
- }
33232
- function clampInteger(value, fallback, minimum, maximum, field) {
33233
- const resolved = value ?? fallback;
33234
- if (!Number.isFinite(resolved)) {
33235
- throw new JobRejectedError(`${field} must be a finite number`);
33236
- }
33237
- return Math.min(maximum, Math.max(minimum, Math.trunc(resolved)));
33238
- }
33239
- async function responseBody(response) {
33240
- try {
33241
- return await response.json();
33242
- } catch {
33243
- return null;
33244
- }
33245
- }
33246
- function gatewayErrorBody(body, fallback) {
33247
- if (!isRecord2(body)) return { code: null, message: fallback };
33248
- const code = typeof body["code"] === "string" ? body["code"] : null;
33249
- const message = typeof body["error"] === "string" ? body["error"] : typeof body["message"] === "string" ? body["message"] : fallback;
33250
- const reason = typeof body["reason"] === "string" ? body["reason"] : void 0;
33251
- const details = isRecord2(body["details"]) ? body["details"] : void 0;
33252
- return {
33253
- code,
33254
- message,
33255
- ...reason ? { reason } : {},
33256
- ...details ? { details } : {}
33257
- };
33258
- }
33259
- async function rejectedResponse(response, fallback) {
33260
- const parsed = gatewayErrorBody(await responseBody(response), fallback);
33261
- const details = response.status === HTTP_UNAUTHORIZED && parsed.reason ? { ...parsed.details, reason: parsed.reason } : parsed.details;
33262
- const message = response.status === HTTP_UNAUTHORIZED && parsed.reason ? `${parsed.message}: ${parsed.reason}` : parsed.message;
33263
- if (response.status === HTTP_FORBIDDEN) {
33264
- if (parsed.code === "BUILDER_UNKNOWN") {
33265
- return new BuilderUnknownError(parsed.message, details);
33144
+ discovery: {
33145
+ parent: "ComputeEngine",
33146
+ getter: "computeEngineTreasury"
33266
33147
  }
33267
- if (parsed.code === "GRANT_INVALID") {
33268
- return new GrantInvalidError(parsed.message, details);
33148
+ },
33149
+ QueryEngine: {
33150
+ addresses: {
33151
+ 14800: "0xd25Eb66EA2452cf3238A2eC6C1FD1B7F5B320490",
33152
+ 1480: "0xd25Eb66EA2452cf3238A2eC6C1FD1B7F5B320490"
33269
33153
  }
33270
- if (parsed.code === "OWNER_NOT_READY") {
33271
- return new OwnerNotReadyError(parsed.message, details);
33154
+ },
33155
+ VanaTreasury: {
33156
+ addresses: {
33157
+ 14800: "0x8B32Ef32f22e72cc25D53f6E858f57cAe7E198f9",
33158
+ 1480: "0x8B32Ef32f22e72cc25D53f6E858f57cAe7E198f9"
33159
+ },
33160
+ discovery: {
33161
+ parent: "QueryEngine",
33162
+ getter: "queryEngineTreasury"
33272
33163
  }
33273
- }
33274
- if (response.status === HTTP_NOT_FOUND) {
33275
- return new JobNotFoundError(parsed.message, details);
33276
- }
33277
- if (response.status === HTTP_CONFLICT && parsed.code === "JOB_ID_TAKEN") {
33278
- return new JobIdTakenError(parsed.message, details);
33279
- }
33280
- if (response.status === HTTP_PAYLOAD_TOO_LARGE) {
33281
- return new JobRequestTooLargeError(parsed.message, parsed.code, details);
33282
- }
33164
+ },
33165
+ DataRefinerRegistry: {
33166
+ addresses: {
33167
+ 14800: "0x93c3EF89369fDcf08Be159D9DeF0F18AB6Be008c",
33168
+ 1480: "0x93c3EF89369fDcf08Be159D9DeF0F18AB6Be008c"
33169
+ }
33170
+ },
33171
+ ComputeInstructionRegistry: {
33172
+ addresses: {
33173
+ 14800: "0x5786B12b4c6Ba2bFAF0e77Ed30Bf6d32805563A5",
33174
+ 1480: "0x5786B12b4c6Ba2bFAF0e77Ed30Bf6d32805563A5"
33175
+ }
33176
+ },
33177
+ // ========================================
33178
+ // TEE POOLS (Canonical Deployments)
33179
+ // ========================================
33180
+ TeePoolPhala: {
33181
+ addresses: {
33182
+ 14800: "0xE8EC6BD73b23Ad40E6B9a6f4bD343FAc411bD99A",
33183
+ 1480: "0xE8EC6BD73b23Ad40E6B9a6f4bD343FAc411bD99A"
33184
+ }
33185
+ },
33186
+ TeePoolEphemeralStandard: {
33187
+ addresses: {
33188
+ 14800: "0xe124bae846D5ec157f75Bd9e68ca87C4d2AB835A",
33189
+ 1480: "0xe124bae846D5ec157f75Bd9e68ca87C4d2AB835A"
33190
+ }
33191
+ },
33192
+ TeePoolPersistentStandard: {
33193
+ addresses: {
33194
+ 14800: "0xe8bB8d0629651Cf33e0845d743976Dc1f0971d76",
33195
+ 1480: "0xe8bB8d0629651Cf33e0845d743976Dc1f0971d76"
33196
+ }
33197
+ },
33198
+ TeePoolPersistentGpu: {
33199
+ addresses: {
33200
+ 14800: "0x1c346Cd74f8551f8fa13f3F4b6b8dAE22338E6a9",
33201
+ 1480: "0x1c346Cd74f8551f8fa13f3F4b6b8dAE22338E6a9"
33202
+ }
33203
+ },
33204
+ TeePoolDedicatedStandard: {
33205
+ addresses: {
33206
+ 14800: "0xf024b7ac5E8417416f53B41ecfa58C8e9396687d",
33207
+ 1480: "0xf024b7ac5E8417416f53B41ecfa58C8e9396687d"
33208
+ }
33209
+ },
33210
+ TeePoolDedicatedGpu: {
33211
+ addresses: {
33212
+ 14800: "0xB1686FA9620bBf851714d1cB47b8a4Bf4664644E",
33213
+ 1480: "0xB1686FA9620bBf851714d1cB47b8a4Bf4664644E"
33214
+ }
33215
+ },
33216
+ // ========================================
33217
+ // VANA EPOCH / DLP REGISTRY
33218
+ // ========================================
33219
+ // Note: DLP rewards-specific contracts (DLPPerformance, DLPRewardDeployer,
33220
+ // DLPRewardDeployerTreasury, DLPRewardSwap, SwapHelper) were removed in the
33221
+ // protocol unification cleanup. VanaEpoch, DLPRegistry, and DLPRegistryTreasury
33222
+ // are kept because they may be referenced beyond the rewards system.
33223
+ VanaEpoch: {
33224
+ addresses: {
33225
+ 14800: "0x2063cFF0609D59bCCc196E20Eb58A8696a6b15A0",
33226
+ 1480: "0x2063cFF0609D59bCCc196E20Eb58A8696a6b15A0"
33227
+ }
33228
+ },
33229
+ DLPRegistry: {
33230
+ addresses: {
33231
+ 14800: "0x4D59880a924526d1dD33260552Ff4328b1E18a43",
33232
+ 1480: "0x4D59880a924526d1dD33260552Ff4328b1E18a43"
33233
+ }
33234
+ },
33235
+ DLPRegistryTreasury: {
33236
+ addresses: {
33237
+ 14800: "0xb12ce1d27bEeFe39b6F0110b1AB77C21Aa0c9F9a",
33238
+ 1480: "0xb12ce1d27bEeFe39b6F0110b1AB77C21Aa0c9F9a"
33239
+ },
33240
+ discovery: {
33241
+ parent: "DLPRegistry",
33242
+ getter: "treasury"
33243
+ }
33244
+ },
33245
+ // ========================================
33246
+ // VANA POOL (STAKING)
33247
+ // ========================================
33248
+ VanaPoolStaking: {
33249
+ addresses: {
33250
+ 14800: "0x641C18E2F286c86f96CE95C8ec1EB9fC0415Ca0e",
33251
+ 1480: "0x641C18E2F286c86f96CE95C8ec1EB9fC0415Ca0e"
33252
+ }
33253
+ },
33254
+ VanaPoolTreasury: {
33255
+ addresses: {
33256
+ 14800: "0x143BE72CF2541604A7691933CAccd6D9cC17c003",
33257
+ 1480: "0x143BE72CF2541604A7691933CAccd6D9cC17c003"
33258
+ },
33259
+ discovery: {
33260
+ parent: "VanaPoolStaking",
33261
+ getter: "vanaPoolTreasury"
33262
+ }
33263
+ },
33264
+ VanaPoolEntity: {
33265
+ addresses: {
33266
+ 14800: "0x44f20490A82e1f1F1cC25Dd3BA8647034eDdce30",
33267
+ 1480: "0x44f20490A82e1f1F1cC25Dd3BA8647034eDdce30"
33268
+ },
33269
+ discovery: {
33270
+ parent: "VanaPoolStaking",
33271
+ getter: "vanaPoolEntity"
33272
+ }
33273
+ },
33274
+ // ========================================
33275
+ // DLP DEPLOYMENT & TOKEN SYSTEM
33276
+ // ========================================
33277
+ DATFactory: {
33278
+ addresses: {
33279
+ 14800: "0x40f8bccF35a75ecef63BC3B1B3E06ffEB9220644",
33280
+ 1480: "0x40f8bccF35a75ecef63BC3B1B3E06ffEB9220644"
33281
+ }
33282
+ },
33283
+ DAT: {
33284
+ addresses: {
33285
+ 14800: "0xA706b93ccED89f13340673889e29F0a5cd84212d",
33286
+ 1480: "0xA706b93ccED89f13340673889e29F0a5cd84212d"
33287
+ }
33288
+ },
33289
+ DATPausable: {
33290
+ addresses: {
33291
+ 14800: "0xe69FE86f0B95cC2f8416Fe22815c85DC8887e76e",
33292
+ 1480: "0xe69FE86f0B95cC2f8416Fe22815c85DC8887e76e"
33293
+ }
33294
+ },
33295
+ DATVotes: {
33296
+ addresses: {
33297
+ 14800: "0xaE04c8A77E9B27869eb563720524A9aE0baf1831",
33298
+ 1480: "0xaE04c8A77E9B27869eb563720524A9aE0baf1831"
33299
+ }
33300
+ },
33301
+ // ========================================
33302
+ // EXTERNAL DEPENDENCIES (DeFi)
33303
+ // ========================================
33304
+ WVANA: {
33305
+ addresses: {
33306
+ 14800: "0xbccc4b4c6530F82FE309c5E845E50b5E9C89f2AD",
33307
+ 1480: "0x00EDdD9621Fb08436d0331c149D1690909a5906d"
33308
+ }
33309
+ },
33310
+ UniswapV3NonfungiblePositionManager: {
33311
+ addresses: {
33312
+ 14800: "0x48Bd633f4B9128a38Ebb4a48b6975EB3Eaf1931b",
33313
+ 1480: "0x45a2992e1bFdCF9b9AcE0a84A238f2E56F481816"
33314
+ }
33315
+ },
33316
+ UniswapV3QuoterV2: {
33317
+ addresses: {
33318
+ 14800: "0x3152246f3CD4dD465292Dd4Ffd792E2Cf602e332",
33319
+ 1480: "0x1b13728ea3C90863990aC0e05987CfeC1888908c"
33320
+ }
33321
+ },
33322
+ // ========================================
33323
+ // UTILITY CONTRACTS
33324
+ // ========================================
33325
+ Multicall3: {
33326
+ addresses: {
33327
+ 14800: "0xD8d2dFca27E8797fd779F8547166A2d3B29d360E",
33328
+ 1480: "0xD8d2dFca27E8797fd779F8547166A2d3B29d360E"
33329
+ }
33330
+ },
33331
+ Multisend: {
33332
+ addresses: {
33333
+ 14800: "0x8807e8BCDFbaA8c2761760f3FBA37F6f7F2C5b2d",
33334
+ 1480: "0x8807e8BCDFbaA8c2761760f3FBA37F6f7F2C5b2d"
33335
+ }
33336
+ }
33337
+ };
33338
+
33339
+ // src/protocol/escrow.ts
33340
+ import { isHex as isHex2 } from "viem";
33341
+ var GENERIC_PAYMENT_TYPES = {
33342
+ GenericPayment: [
33343
+ { name: "payerAddress", type: "address" },
33344
+ { name: "opType", type: "string" },
33345
+ { name: "opId", type: "bytes32" },
33346
+ { name: "asset", type: "address" },
33347
+ { name: "amount", type: "uint256" },
33348
+ { name: "paymentNonce", type: "uint256" }
33349
+ ]
33350
+ };
33351
+ function genericPaymentDomain(chainId, escrowContract) {
33352
+ return {
33353
+ name: "Vana Data Portability",
33354
+ version: "1",
33355
+ chainId,
33356
+ verifyingContract: escrowContract
33357
+ };
33358
+ }
33359
+ var ESCROW_DEPOSIT_ABI = [
33360
+ {
33361
+ type: "function",
33362
+ name: "depositNative",
33363
+ stateMutability: "payable",
33364
+ inputs: [{ name: "account", type: "address" }],
33365
+ outputs: []
33366
+ },
33367
+ {
33368
+ type: "function",
33369
+ name: "depositToken",
33370
+ stateMutability: "nonpayable",
33371
+ inputs: [
33372
+ { name: "account", type: "address" },
33373
+ { name: "token", type: "address" },
33374
+ { name: "amount", type: "uint256" }
33375
+ ],
33376
+ outputs: []
33377
+ }
33378
+ ];
33379
+ var NATIVE_ASSET_ADDRESS = "0x0000000000000000000000000000000000000000";
33380
+ var EscrowWithdrawalLifecycleError = class extends Error {
33381
+ constructor(httpStatus, result) {
33382
+ super(result.error);
33383
+ this.httpStatus = httpStatus;
33384
+ this.result = result;
33385
+ }
33386
+ httpStatus;
33387
+ result;
33388
+ name = "EscrowWithdrawalLifecycleError";
33389
+ };
33390
+ var EscrowWithdrawalRejectionError = class extends Error {
33391
+ constructor(httpStatus, result) {
33392
+ super(result.error);
33393
+ this.httpStatus = httpStatus;
33394
+ this.result = result;
33395
+ }
33396
+ httpStatus;
33397
+ result;
33398
+ name = "EscrowWithdrawalRejectionError";
33399
+ };
33400
+ function createEscrowGatewayClient(baseUrl) {
33401
+ const base = baseUrl.replace(/\/+$/, "");
33402
+ async function throwOnError(res, context) {
33403
+ if (!res.ok) {
33404
+ let detail = "";
33405
+ try {
33406
+ const body = await res.json();
33407
+ if (body.error) detail = `: ${body.error}`;
33408
+ } catch {
33409
+ }
33410
+ throw new Error(
33411
+ `Escrow gateway error (${context}): ${res.status} ${res.statusText}${detail}`
33412
+ );
33413
+ }
33414
+ }
33415
+ async function throwOnWithdrawError(res) {
33416
+ if (res.ok) return;
33417
+ let body;
33418
+ try {
33419
+ body = await res.json();
33420
+ } catch {
33421
+ throw new Error(
33422
+ `Escrow gateway error (POST /v1/escrow/withdraw): ${res.status} ${res.statusText}`
33423
+ );
33424
+ }
33425
+ if (isEscrowWithdrawalFailureResult(body)) {
33426
+ throw new EscrowWithdrawalLifecycleError(res.status, body);
33427
+ }
33428
+ if (isEscrowWithdrawalRejectedResult(body)) {
33429
+ throw new EscrowWithdrawalRejectionError(res.status, body);
33430
+ }
33431
+ const error = getGatewayErrorMessage(body);
33432
+ throw new Error(
33433
+ `Escrow gateway error (POST /v1/escrow/withdraw): ${res.status} ${res.statusText}${error ? `: ${error}` : ""}`
33434
+ );
33435
+ }
33436
+ return {
33437
+ async submitDeposit({ txHash }) {
33438
+ const res = await fetch(`${base}/v1/escrow/deposit`, {
33439
+ method: "POST",
33440
+ headers: { "Content-Type": "application/json" },
33441
+ body: JSON.stringify({ txHash })
33442
+ });
33443
+ if (res.status !== 200 && res.status !== 202) {
33444
+ await throwOnError(res, "POST /v1/escrow/deposit");
33445
+ }
33446
+ return res.json();
33447
+ },
33448
+ async getEscrowBalance(account) {
33449
+ const res = await fetch(
33450
+ `${base}/v1/escrow/balance?account=${encodeURIComponent(account)}`
33451
+ );
33452
+ await throwOnError(res, "GET /v1/escrow/balance");
33453
+ return res.json();
33454
+ },
33455
+ async syncEscrowBalance(account) {
33456
+ const res = await fetch(
33457
+ `${base}/v1/escrow/balance/sync?account=${encodeURIComponent(account)}`,
33458
+ { method: "POST" }
33459
+ );
33460
+ await throwOnError(res, "POST /v1/escrow/balance/sync");
33461
+ return res.json();
33462
+ },
33463
+ async payForOp({
33464
+ payerAddress,
33465
+ opType,
33466
+ opId,
33467
+ asset,
33468
+ amount,
33469
+ paymentNonce,
33470
+ signature,
33471
+ accessRecord
33472
+ }) {
33473
+ const res = await fetch(`${base}/v1/escrow/pay`, {
33474
+ method: "POST",
33475
+ headers: {
33476
+ "Content-Type": "application/json",
33477
+ Authorization: `Web3Signed ${signature}`
33478
+ },
33479
+ body: JSON.stringify({
33480
+ payerAddress,
33481
+ opType,
33482
+ opId,
33483
+ asset,
33484
+ amount,
33485
+ paymentNonce,
33486
+ ...accessRecord ? { accessRecord } : {}
33487
+ })
33488
+ });
33489
+ await throwOnError(res, "POST /v1/escrow/pay");
33490
+ return res.json();
33491
+ },
33492
+ async withdraw({
33493
+ account,
33494
+ asset,
33495
+ amount,
33496
+ withdrawNonce,
33497
+ deadline,
33498
+ signature
33499
+ }) {
33500
+ const res = await fetch(`${base}/v1/escrow/withdraw`, {
33501
+ method: "POST",
33502
+ headers: {
33503
+ "Content-Type": "application/json",
33504
+ Authorization: `Web3Signed ${signature}`
33505
+ },
33506
+ body: JSON.stringify({
33507
+ account,
33508
+ asset,
33509
+ amount,
33510
+ withdrawNonce,
33511
+ deadline
33512
+ })
33513
+ });
33514
+ await throwOnWithdrawError(res);
33515
+ return res.json();
33516
+ },
33517
+ async getWithdrawNonce(account) {
33518
+ const res = await fetch(
33519
+ `${base}/v1/escrow/withdraw/nonce?account=${encodeURIComponent(account)}`,
33520
+ { cache: "no-store" }
33521
+ );
33522
+ await throwOnError(res, "GET /v1/escrow/withdraw/nonce");
33523
+ const body = await res.json();
33524
+ if (!isWithdrawNonceResponse(body, account)) {
33525
+ throw new Error(
33526
+ "GET /v1/escrow/withdraw/nonce: invalid response structure"
33527
+ );
33528
+ }
33529
+ return body;
33530
+ }
33531
+ };
33532
+ }
33533
+ function getGatewayErrorMessage(body) {
33534
+ if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
33535
+ return body.error;
33536
+ }
33537
+ return void 0;
33538
+ }
33539
+ function isEscrowWithdrawalFailureResult(body) {
33540
+ if (typeof body !== "object" || body === null) return false;
33541
+ const value = body;
33542
+ return value.success === false && (value.status === "retryable" || value.status === "reorged" || value.status === "failed") && typeof value.error === "string" && isAddressHex(value.account) && isAddressHex(value.asset) && isUint256Decimal(value.amount) && isUint256Decimal(value.withdrawNonce) && isUint256Decimal(value.deadline) && (isHash(value.txHash) || value.txHash === null) && (!("blockNumber" in value) || isBlockNumber(value.blockNumber));
33543
+ }
33544
+ function isEscrowWithdrawalRejectedResult(body) {
33545
+ if (typeof body !== "object" || body === null) return false;
33546
+ const value = body;
33547
+ return value.success === false && value.status === "rejected" && isWithdrawalRejectionCode(value.code) && typeof value.error === "string" && isAddressHex(value.account) && isAddressHex(value.asset) && isUint256Decimal(value.amount) && isUint256Decimal(value.withdrawNonce) && isUint256Decimal(value.deadline) && optionalUint256Decimal(value.balance) && optionalUint256Decimal(value.authorizedAmount) && optionalUint256Decimal(value.withdrawingAmount) && optionalUint256Decimal(value.availableAmount) && optionalUint256Decimal(value.requestedAmount) && optionalUint256Decimal(value.minimumAmount);
33548
+ }
33549
+ function isWithdrawalRejectionCode(value) {
33550
+ return value === "below_minimum" || value === "deadline_too_far" || value === "expired" || value === "insufficient_available" || value === "stale_nonce";
33551
+ }
33552
+ function optionalUint256Decimal(value) {
33553
+ return value === void 0 || isUint256Decimal(value);
33554
+ }
33555
+ function isAddressHex(value) {
33556
+ return typeof value === "string" && isHex2(value, { strict: true }) && value.length === 42;
33557
+ }
33558
+ function isHash(value) {
33559
+ return typeof value === "string" && isHex2(value, { strict: true }) && value.length === 66;
33560
+ }
33561
+ function isUint256Decimal(value) {
33562
+ if (typeof value !== "string" || value.length === 0 || value.length > 78) {
33563
+ return false;
33564
+ }
33565
+ if (!/^(0|[1-9]\d*)$/.test(value)) return false;
33566
+ return BigInt(value) <= 2n ** 256n - 1n;
33567
+ }
33568
+ function isBlockNumber(value) {
33569
+ return value === null || isUint256Decimal(value);
33570
+ }
33571
+ function isWithdrawNonceResponse(body, requestedAccount) {
33572
+ if (typeof body !== "object" || body === null) return false;
33573
+ const value = body;
33574
+ if (value.success !== true) return false;
33575
+ if (!isAddressHex(value.account)) return false;
33576
+ if (value.account.toLowerCase() !== requestedAccount.toLowerCase())
33577
+ return false;
33578
+ if (typeof value.chainId !== "string") return false;
33579
+ if (!/^(0|[1-9]\d*)$/.test(value.chainId)) return false;
33580
+ const isLastNull = value.lastWithdrawNonce === null;
33581
+ const lastNonceValid = isLastNull || isUint256Decimal(value.lastWithdrawNonce);
33582
+ if (!lastNonceValid) return false;
33583
+ if (!isUint256Decimal(value.nextWithdrawNonce)) return false;
33584
+ if (isLastNull) {
33585
+ return value.nextWithdrawNonce === "1";
33586
+ }
33587
+ const lastNonce = BigInt(value.lastWithdrawNonce);
33588
+ const nextNonce = BigInt(value.nextWithdrawNonce);
33589
+ const expectedNextNonce = lastNonce + 1n;
33590
+ if (expectedNextNonce > 2n ** 256n - 1n) return false;
33591
+ return nextNonce === expectedNextNonce;
33592
+ }
33593
+
33594
+ // src/protocol/write-signer.ts
33595
+ import { WriteRequestError } from "./errors.js";
33596
+ function isRecord(value) {
33597
+ return value !== null && typeof value === "object";
33598
+ }
33599
+ function isViemWriteAccount(source) {
33600
+ return isRecord(source) && source.type === "local" && typeof source.address === "string" && typeof source.signMessage === "function";
33601
+ }
33602
+ function isViemWriteWalletClient(source) {
33603
+ return isRecord(source) && typeof source.signMessage === "function" && source.type !== "local" && (source.type === "walletClient" || "transport" in source);
33604
+ }
33605
+ function accountAddress(account) {
33606
+ return typeof account === "string" ? account : account.address;
33607
+ }
33608
+ function resolveWriteSigner(source, options = {}) {
33609
+ if (isViemWriteWalletClient(source)) {
33610
+ const account = options.account ?? source.account;
33611
+ if (account === void 0) {
33612
+ throw new WriteRequestError(
33613
+ "Viem wallet client requires an account option or account property"
33614
+ );
33615
+ }
33616
+ return {
33617
+ address: accountAddress(account),
33618
+ signMessage: (message) => source.signMessage({ account, message })
33619
+ };
33620
+ }
33621
+ if (isViemWriteAccount(source)) {
33622
+ return {
33623
+ address: source.address,
33624
+ signMessage: (message) => source.signMessage({ message })
33625
+ };
33626
+ }
33627
+ if (!isRecord(source) || typeof source.signMessage !== "function") {
33628
+ throw new WriteRequestError(
33629
+ "signer must be a viem LocalAccount, a viem WalletClient, or a { signMessage } object"
33630
+ );
33631
+ }
33632
+ return source;
33633
+ }
33634
+
33635
+ // src/protocol/jobs-client.ts
33636
+ var IDENTITY_PATH = "/v1/identity";
33637
+ var JOBS_PATH = "/v1/jobs";
33638
+ var JOB_QUOTE_PATH = "/v1/jobs/quote";
33639
+ var JOB_EXECUTE_PATH = "/v1/jobs/execute";
33640
+ var JOB_ACCESS_OP_TYPE = "job_access";
33641
+ var AUTHORIZATION_HEADER = "Authorization";
33642
+ var CONTENT_TYPE_HEADER = "Content-Type";
33643
+ var JSON_CONTENT_TYPE = "application/json";
33644
+ var GET_METHOD = "GET";
33645
+ var POST_METHOD = "POST";
33646
+ var RAW_READ_OPERATION = "raw_read";
33647
+ var SEALED_IDENTITY_STATE = "sealed";
33648
+ var HTTP_OK = 200;
33649
+ var HTTP_ACCEPTED = 202;
33650
+ var HTTP_UNAUTHORIZED = 401;
33651
+ var HTTP_FORBIDDEN = 403;
33652
+ var HTTP_NOT_FOUND = 404;
33653
+ var HTTP_CONFLICT = 409;
33654
+ var HTTP_PAYMENT_REQUIRED = 402;
33655
+ var HTTP_PAYLOAD_TOO_LARGE = 413;
33656
+ var NONCE_TIMESTAMP_SHIFT = 32n;
33657
+ var UINT256_DECIMAL = /^(0|[1-9]\d*)$/;
33658
+ var POSITIVE_UINT256_DECIMAL = /^[1-9]\d*$/;
33659
+ var MILLISECONDS_PER_SECOND = 1e3;
33660
+ var DEFAULT_JOB_TIMEOUT_MS = 12e4;
33661
+ var DEFAULT_JOB_POLL_MS = CLAIM_POLL_FLOOR_MS;
33662
+ var TERMINAL_JOB_STATES = /* @__PURE__ */ new Set([
33663
+ "completed",
33664
+ "failed",
33665
+ "expired",
33666
+ "cancelled"
33667
+ ]);
33668
+ function isRecord2(value) {
33669
+ return value !== null && typeof value === "object" && !Array.isArray(value);
33670
+ }
33671
+ function normalizeGateway(gatewayUrl) {
33672
+ try {
33673
+ const url = new URL(gatewayUrl);
33674
+ if (url.pathname !== "/" || url.search !== "" || url.hash !== "") {
33675
+ throw new JobRejectedError(
33676
+ "gatewayUrl must be an origin without a path, query, or fragment"
33677
+ );
33678
+ }
33679
+ return {
33680
+ baseUrl: url.origin,
33681
+ audience: url.origin
33682
+ };
33683
+ } catch (error) {
33684
+ if (error instanceof JobRejectedError) throw error;
33685
+ throw new JobRejectedError(
33686
+ "gatewayUrl must be an absolute URL",
33687
+ void 0,
33688
+ null,
33689
+ {
33690
+ cause: error instanceof Error ? error.message : String(error)
33691
+ }
33692
+ );
33693
+ }
33694
+ }
33695
+ function resolveFetch(fetchFn) {
33696
+ const resolved = fetchFn ?? globalThis.fetch;
33697
+ if (resolved === void 0) {
33698
+ throw new JobRejectedError("No fetch implementation available");
33699
+ }
33700
+ return resolved;
33701
+ }
33702
+ function sourcePublicKey(source) {
33703
+ if (isRecord2(source) && typeof source["publicKey"] === "string") {
33704
+ return source["publicKey"];
33705
+ }
33706
+ return void 0;
33707
+ }
33708
+ function resolveBuilder(options) {
33709
+ if (options.builderPrivateKey && options.builderAccount) {
33710
+ throw new JobRejectedError(
33711
+ "Provide builderPrivateKey or builderAccount, not both"
33712
+ );
33713
+ }
33714
+ let source;
33715
+ try {
33716
+ source = options.builderPrivateKey ? privateKeyToAccount(options.builderPrivateKey) : options.builderAccount;
33717
+ } catch (error) {
33718
+ throw new JobRejectedError("Invalid builder private key", void 0, null, {
33719
+ cause: error instanceof Error ? error.message : String(error)
33720
+ });
33721
+ }
33722
+ if (!source) {
33723
+ throw new JobRejectedError(
33724
+ "builderPrivateKey or builderAccount is required"
33725
+ );
33726
+ }
33727
+ let signer;
33728
+ try {
33729
+ signer = resolveWriteSigner(source);
33730
+ } catch (error) {
33731
+ throw new JobRejectedError("Invalid builder signer", void 0, null, {
33732
+ cause: error instanceof Error ? error.message : String(error)
33733
+ });
33734
+ }
33735
+ const publicKey = sourcePublicKey(source);
33736
+ if (!signer.address || !publicKey) {
33737
+ throw new JobRejectedError(
33738
+ "Builder signer must expose both address and publicKey"
33739
+ );
33740
+ }
33741
+ const typedDataSigner = source.signTypedData;
33742
+ return {
33743
+ builder: {
33744
+ address: signer.address,
33745
+ publicKey,
33746
+ signMessage: signer.signMessage,
33747
+ ...typedDataSigner ? {
33748
+ signTypedData: typedDataSigner.bind(
33749
+ source
33750
+ )
33751
+ } : {}
33752
+ },
33753
+ ...options.builderPrivateKey ? { privateKey: options.builderPrivateKey } : {}
33754
+ };
33755
+ }
33756
+ function clampInteger(value, fallback, minimum, maximum, field) {
33757
+ const resolved = value ?? fallback;
33758
+ if (!Number.isFinite(resolved)) {
33759
+ throw new JobRejectedError(`${field} must be a finite number`);
33760
+ }
33761
+ return Math.min(maximum, Math.max(minimum, Math.trunc(resolved)));
33762
+ }
33763
+ async function responseBody(response) {
33764
+ try {
33765
+ return await response.json();
33766
+ } catch {
33767
+ return null;
33768
+ }
33769
+ }
33770
+ function gatewayErrorBody(body, fallback) {
33771
+ if (!isRecord2(body)) return { code: null, message: fallback };
33772
+ const code = typeof body["code"] === "string" ? body["code"] : null;
33773
+ const message = typeof body["error"] === "string" ? body["error"] : typeof body["message"] === "string" ? body["message"] : fallback;
33774
+ const reason = typeof body["reason"] === "string" ? body["reason"] : void 0;
33775
+ const details = isRecord2(body["details"]) ? body["details"] : void 0;
33776
+ return {
33777
+ code,
33778
+ message,
33779
+ ...reason ? { reason } : {},
33780
+ ...details ? { details } : {}
33781
+ };
33782
+ }
33783
+ async function rejectedResponse(response, fallback) {
33784
+ const parsed = gatewayErrorBody(await responseBody(response), fallback);
33785
+ const details = response.status === HTTP_UNAUTHORIZED && parsed.reason ? { ...parsed.details, reason: parsed.reason } : parsed.details;
33786
+ const message = response.status === HTTP_UNAUTHORIZED && parsed.reason ? `${parsed.message}: ${parsed.reason}` : parsed.message;
33787
+ if (response.status === HTTP_FORBIDDEN) {
33788
+ if (parsed.code === "BUILDER_UNKNOWN") {
33789
+ return new BuilderUnknownError(parsed.message, details);
33790
+ }
33791
+ if (parsed.code === "GRANT_INVALID") {
33792
+ return new GrantInvalidError(parsed.message, details);
33793
+ }
33794
+ if (parsed.code === "OWNER_NOT_READY") {
33795
+ return new OwnerNotReadyError(parsed.message, details);
33796
+ }
33797
+ }
33798
+ if (response.status === HTTP_NOT_FOUND) {
33799
+ return new JobNotFoundError(parsed.message, details);
33800
+ }
33801
+ if (response.status === HTTP_CONFLICT && parsed.code === "JOB_ID_TAKEN") {
33802
+ return new JobIdTakenError(parsed.message, details);
33803
+ }
33804
+ if (response.status === HTTP_PAYLOAD_TOO_LARGE) {
33805
+ return new JobRequestTooLargeError(parsed.message, parsed.code, details);
33806
+ }
33283
33807
  return new JobRejectedError(message, response.status, parsed.code, details);
33284
33808
  }
33285
33809
  function requireStatus(value, status) {
@@ -33308,7 +33832,7 @@ function isResultHandle(value) {
33308
33832
  function hasMatchingIdentityKey(value) {
33309
33833
  const address = value["address"];
33310
33834
  const publicKey = value["publicKey"];
33311
- if (typeof address !== "string" || !isAddress2(address) || typeof publicKey !== "string" || !isHex2(publicKey)) {
33835
+ if (typeof address !== "string" || !isAddress2(address) || typeof publicKey !== "string" || !isHex3(publicKey)) {
33312
33836
  return false;
33313
33837
  }
33314
33838
  try {
@@ -33321,7 +33845,7 @@ function hasExpectedIdentity(value, owner, chainId) {
33321
33845
  const identityOwner = value["ownerAddress"];
33322
33846
  const identityChainId = value["chainId"];
33323
33847
  const identityUserPsId = value["userPsId"];
33324
- if (!hasMatchingIdentityKey(value) || typeof identityOwner !== "string" || !isAddress2(identityOwner) || typeof identityChainId !== "number" || typeof identityUserPsId !== "string" || !isHex2(identityUserPsId)) {
33848
+ if (!hasMatchingIdentityKey(value) || typeof identityOwner !== "string" || !isAddress2(identityOwner) || typeof identityChainId !== "number" || typeof identityUserPsId !== "string" || !isHex3(identityUserPsId)) {
33325
33849
  return false;
33326
33850
  }
33327
33851
  return isAddressEqual2(identityOwner, owner) && identityChainId === chainId && identityUserPsId.toLowerCase() === userPsId(chainId, owner).toLowerCase();
@@ -33329,6 +33853,51 @@ function hasExpectedIdentity(value, owner, chainId) {
33329
33853
  function sleep2(ms) {
33330
33854
  return new Promise((resolve) => setTimeout(resolve, ms));
33331
33855
  }
33856
+ function resolveEscrowContract(options) {
33857
+ if (options.escrowContract) return options.escrowContract;
33858
+ const addresses = CONTRACTS2["DataPortabilityEscrow"]?.addresses;
33859
+ const address = addresses?.[options.chainId];
33860
+ if (!address || !isAddress2(address)) {
33861
+ throw new JobRejectedError(
33862
+ `No DataPortabilityEscrow address for chain ${options.chainId}; pass escrowContract`
33863
+ );
33864
+ }
33865
+ return address;
33866
+ }
33867
+ function nextPaymentNonce() {
33868
+ const random = new Uint32Array(1);
33869
+ globalThis.crypto.getRandomValues(random);
33870
+ return (BigInt(Date.now()) << NONCE_TIMESTAMP_SHIFT) + BigInt(random[0] ?? 0);
33871
+ }
33872
+ function parseJobQuote(body) {
33873
+ if (!isRecord2(body)) return null;
33874
+ const { chainId, price, asset, payable, enforced } = body;
33875
+ if (typeof chainId !== "number" || !Number.isSafeInteger(chainId))
33876
+ return null;
33877
+ if (typeof price !== "string" || !UINT256_DECIMAL.test(price)) return null;
33878
+ if (typeof asset !== "string" || !isAddress2(asset)) return null;
33879
+ if (typeof payable !== "boolean" || typeof enforced !== "boolean")
33880
+ return null;
33881
+ return { chainId, price, asset, payable, enforced };
33882
+ }
33883
+ async function paymentQuote(response) {
33884
+ const body = await responseBody(response);
33885
+ const asset = isRecord2(body) ? body["asset"] : void 0;
33886
+ const amount = isRecord2(body) ? body["amount"] : void 0;
33887
+ if (typeof asset !== "string" || !isAddress2(asset) || typeof amount !== "string" || !POSITIVE_UINT256_DECIMAL.test(amount)) {
33888
+ throw new JobRejectedError(
33889
+ "Gateway asked for payment without a usable quote",
33890
+ response.status
33891
+ );
33892
+ }
33893
+ return { asset, amount };
33894
+ }
33895
+ async function paymentRefusal(response) {
33896
+ const body = await responseBody(response);
33897
+ const parsed = isRecord2(body) ? body : {};
33898
+ const message = typeof parsed["error"] === "string" ? parsed["error"] : "This read requires payment the builder escrow cannot back";
33899
+ return { message, details: parsed };
33900
+ }
33332
33901
  function requireFiniteDuration(value, field) {
33333
33902
  if (!Number.isFinite(value)) {
33334
33903
  throw new JobRejectedError(`${field} must be a finite number`);
@@ -33341,6 +33910,73 @@ function createJobsClient(options) {
33341
33910
  const { builder, privateKey } = resolveBuilder(options);
33342
33911
  const ecies = options.ecies ?? new NodeECIESUint8Provider();
33343
33912
  const now = options.now ?? (() => /* @__PURE__ */ new Date());
33913
+ async function signQuote(jobId, quote) {
33914
+ if (!builder.signTypedData) {
33915
+ throw new JobRejectedError(
33916
+ "This read is charged, but the builder signer cannot sign typed data"
33917
+ );
33918
+ }
33919
+ const paymentNonce = nextPaymentNonce();
33920
+ const signature = await builder.signTypedData({
33921
+ domain: genericPaymentDomain(
33922
+ options.chainId,
33923
+ resolveEscrowContract(options)
33924
+ ),
33925
+ types: GENERIC_PAYMENT_TYPES,
33926
+ primaryType: "GenericPayment",
33927
+ message: {
33928
+ payerAddress: builder.address,
33929
+ opType: JOB_ACCESS_OP_TYPE,
33930
+ opId: keccak2562(toHex9(jobId.toLowerCase())),
33931
+ asset: quote.asset,
33932
+ amount: BigInt(quote.amount),
33933
+ paymentNonce
33934
+ }
33935
+ });
33936
+ return {
33937
+ signature,
33938
+ amount: quote.amount,
33939
+ asset: quote.asset,
33940
+ paymentNonce: paymentNonce.toString()
33941
+ };
33942
+ }
33943
+ async function postSubmission(submission, wait) {
33944
+ const identifiers = {
33945
+ jobId: submission.jobId,
33946
+ idempotencyKey: submission.idempotencyKey
33947
+ };
33948
+ const bodyBytes = new TextEncoder().encode(JSON.stringify(submission));
33949
+ const authorization = await buildWeb3SignedHeader({
33950
+ signMessage: builder.signMessage,
33951
+ aud: audience,
33952
+ method: POST_METHOD,
33953
+ uri: JOBS_PATH,
33954
+ body: bodyBytes,
33955
+ nonce: randomUUID()
33956
+ });
33957
+ try {
33958
+ return await request(
33959
+ `${baseUrl}${JOBS_PATH}?wait=${wait}`,
33960
+ {
33961
+ method: POST_METHOD,
33962
+ headers: {
33963
+ [AUTHORIZATION_HEADER]: authorization,
33964
+ [CONTENT_TYPE_HEADER]: JSON_CONTENT_TYPE
33965
+ },
33966
+ body: bodyBytes
33967
+ },
33968
+ "Job submission"
33969
+ );
33970
+ } catch (error) {
33971
+ if (error instanceof JobTransportError) {
33972
+ throw new JobTransportError(error.message, error.cause, {
33973
+ ...error.details,
33974
+ ...identifiers
33975
+ });
33976
+ }
33977
+ throw error;
33978
+ }
33979
+ }
33344
33980
  async function request(url, init, description) {
33345
33981
  try {
33346
33982
  return await fetchFn(url, init);
@@ -33396,7 +34032,8 @@ function createJobsClient(options) {
33396
34032
  "deadlineSeconds"
33397
34033
  );
33398
34034
  const wait = clampInteger(params.wait, 0, 0, MAX_WAIT_SECONDS, "wait");
33399
- const jobId = randomUUID();
34035
+ const jobId = params.jobId ?? randomUUID();
34036
+ const idempotencyKey = params.idempotencyKey ?? randomUUID();
33400
34037
  const nowMs = now().getTime();
33401
34038
  if (!Number.isFinite(nowMs)) {
33402
34039
  throw new JobRejectedError("now must return a valid Date");
@@ -33434,32 +34071,41 @@ function createJobsClient(options) {
33434
34071
  grantId: requestBody.grantId,
33435
34072
  scope: requestBody.scope,
33436
34073
  operation: requestBody.operation,
33437
- idempotencyKey: randomUUID(),
34074
+ idempotencyKey,
33438
34075
  jobId,
33439
34076
  deadline,
33440
- requestCiphertext
34077
+ requestCiphertext,
34078
+ ...params.maxPrice === void 0 ? {} : { maxPrice: params.maxPrice }
33441
34079
  };
33442
- const bodyBytes = new TextEncoder().encode(JSON.stringify(submission));
33443
- const authorization = await buildWeb3SignedHeader({
33444
- signMessage: builder.signMessage,
33445
- aud: audience,
33446
- method: POST_METHOD,
33447
- uri: JOBS_PATH,
33448
- body: bodyBytes,
33449
- nonce: randomUUID()
33450
- });
33451
- const response = await request(
33452
- `${baseUrl}${JOBS_PATH}?wait=${wait}`,
33453
- {
33454
- method: POST_METHOD,
33455
- headers: {
33456
- [AUTHORIZATION_HEADER]: authorization,
33457
- [CONTENT_TYPE_HEADER]: JSON_CONTENT_TYPE
33458
- },
33459
- body: bodyBytes
33460
- },
33461
- "Job submission"
33462
- );
34080
+ let response = await postSubmission(submission, wait);
34081
+ if (response.status === HTTP_PAYMENT_REQUIRED) {
34082
+ const quote = await paymentQuote(response);
34083
+ if (params.maxPrice !== void 0 && BigInt(quote.amount) > BigInt(params.maxPrice)) {
34084
+ throw new PaymentRequiredError(
34085
+ "The quoted price is above the maxPrice you set for this read",
34086
+ {
34087
+ jobId,
34088
+ scope: params.scope,
34089
+ grantId: params.grantId,
34090
+ asset: quote.asset,
34091
+ amount: quote.amount,
34092
+ maxPrice: params.maxPrice
34093
+ }
34094
+ );
34095
+ }
34096
+ submission.payment = await signQuote(jobId, quote);
34097
+ submission.priceAsset = quote.asset;
34098
+ response = await postSubmission(submission, wait);
34099
+ if (response.status === HTTP_PAYMENT_REQUIRED) {
34100
+ const refusal = await paymentRefusal(response);
34101
+ throw new PaymentRequiredError(refusal.message, {
34102
+ jobId,
34103
+ scope: params.scope,
34104
+ grantId: params.grantId,
34105
+ ...refusal.details
34106
+ });
34107
+ }
34108
+ }
33463
34109
  if (!response.ok) {
33464
34110
  throw await rejectedResponse(response, "Job submission rejected");
33465
34111
  }
@@ -33482,6 +34128,40 @@ function createJobsClient(options) {
33482
34128
  response.status
33483
34129
  );
33484
34130
  },
34131
+ async quoteJob() {
34132
+ const authorization = await buildWeb3SignedHeader({
34133
+ signMessage: builder.signMessage,
34134
+ aud: audience,
34135
+ method: GET_METHOD,
34136
+ uri: JOB_QUOTE_PATH,
34137
+ nonce: randomUUID()
34138
+ });
34139
+ const response = await request(
34140
+ `${baseUrl}${JOB_QUOTE_PATH}`,
34141
+ {
34142
+ method: GET_METHOD,
34143
+ headers: { [AUTHORIZATION_HEADER]: authorization }
34144
+ },
34145
+ "Job quote"
34146
+ );
34147
+ if (!response.ok) {
34148
+ throw await rejectedResponse(response, "Job quote rejected");
34149
+ }
34150
+ const quote = parseJobQuote(await responseBody(response));
34151
+ if (!quote) {
34152
+ throw new JobRejectedError(
34153
+ "Gateway returned an undocumented job quote",
34154
+ response.status
34155
+ );
34156
+ }
34157
+ if (quote.chainId !== options.chainId) {
34158
+ throw new JobRejectedError(
34159
+ `Gateway quoted chain ${quote.chainId}, not the configured ${options.chainId}`,
34160
+ response.status
34161
+ );
34162
+ }
34163
+ return quote;
34164
+ },
33485
34165
  async getJob(jobId) {
33486
34166
  const path = `${JOBS_PATH}/${encodeURIComponent(jobId)}`;
33487
34167
  const authorization = await buildWeb3SignedHeader({
@@ -34235,7 +34915,7 @@ async function getOpFee(client, config, opType, opts) {
34235
34915
 
34236
34916
  // src/protocol/escrow-deposit.ts
34237
34917
  import { encodeFunctionData } from "viem";
34238
- var ESCROW_DEPOSIT_ABI = [
34918
+ var ESCROW_DEPOSIT_ABI2 = [
34239
34919
  {
34240
34920
  type: "function",
34241
34921
  name: "depositNative",
@@ -34260,14 +34940,14 @@ function escrowContractAddress(config) {
34260
34940
  }
34261
34941
  function encodeDepositNativeData(input) {
34262
34942
  return encodeFunctionData({
34263
- abi: ESCROW_DEPOSIT_ABI,
34943
+ abi: ESCROW_DEPOSIT_ABI2,
34264
34944
  functionName: "depositNative",
34265
34945
  args: [input.account]
34266
34946
  });
34267
34947
  }
34268
34948
  function encodeDepositTokenData(input) {
34269
34949
  return encodeFunctionData({
34270
- abi: ESCROW_DEPOSIT_ABI,
34950
+ abi: ESCROW_DEPOSIT_ABI2,
34271
34951
  functionName: "depositToken",
34272
34952
  args: [input.account, input.token, input.amount]
34273
34953
  });
@@ -34333,7 +35013,7 @@ function buildMarkDataPointUnavailableRequest(config, input) {
34333
35013
  // src/protocol/data-point-deletion.ts
34334
35014
  import {
34335
35015
  isAddress as isAddress7,
34336
- keccak256 as keccak2563,
35016
+ keccak256 as keccak2564,
34337
35017
  maxUint256,
34338
35018
  stringToBytes as stringToBytes3
34339
35019
  } from "viem";
@@ -34343,7 +35023,7 @@ import { DataPointDeletedError, DataPointNotFoundError } from "./errors.js";
34343
35023
  import {
34344
35024
  encodeAbiParameters,
34345
35025
  isAddress as isAddress6,
34346
- keccak256 as keccak2562
35026
+ keccak256 as keccak2563
34347
35027
  } from "viem";
34348
35028
  import { z } from "zod";
34349
35029
  import { LineageReadError, WriteRequestError as WriteRequestError2 } from "./errors.js";
@@ -34388,7 +35068,7 @@ function deriveDataPointId(ownerAddress, scope) {
34388
35068
  `ownerAddress is not an EVM address: ${String(ownerAddress)}`
34389
35069
  );
34390
35070
  }
34391
- return keccak2562(
35071
+ return keccak2563(
34392
35072
  encodeAbiParameters(
34393
35073
  [
34394
35074
  { name: "ownerAddress", type: "address" },
@@ -34615,7 +35295,7 @@ var TOMBSTONE_METADATA_HASH_PREIMAGE = "vana.data-point.tombstone.metadata.v1";
34615
35295
  var TOMBSTONE_DATA_HASH = "0x30c45ee72fe56d1927701316925ab7ceacd3b6f9267061735d59396f075c6222";
34616
35296
  var TOMBSTONE_METADATA_HASH = "0xc5255a141acd6a2ae55971b62c0a85977c2511989dc114ad2abc2b7644f57d90";
34617
35297
  function computeTombstoneHash(preimage) {
34618
- return keccak2563(stringToBytes3(preimage));
35298
+ return keccak2564(stringToBytes3(preimage));
34619
35299
  }
34620
35300
  function isTombstoneHashes(dataHash, metadataHash) {
34621
35301
  return typeof dataHash === "string" && typeof metadataHash === "string" && dataHash.toLowerCase() === TOMBSTONE_DATA_HASH && metadataHash.toLowerCase() === TOMBSTONE_METADATA_HASH;
@@ -36707,261 +37387,6 @@ function createGatewayClient(baseUrl) {
36707
37387
  };
36708
37388
  }
36709
37389
 
36710
- // src/protocol/escrow.ts
36711
- import { isHex as isHex3 } from "viem";
36712
- var GENERIC_PAYMENT_TYPES = {
36713
- GenericPayment: [
36714
- { name: "payerAddress", type: "address" },
36715
- { name: "opType", type: "string" },
36716
- { name: "opId", type: "bytes32" },
36717
- { name: "asset", type: "address" },
36718
- { name: "amount", type: "uint256" },
36719
- { name: "paymentNonce", type: "uint256" }
36720
- ]
36721
- };
36722
- function genericPaymentDomain(chainId, escrowContract) {
36723
- return {
36724
- name: "Vana Data Portability",
36725
- version: "1",
36726
- chainId,
36727
- verifyingContract: escrowContract
36728
- };
36729
- }
36730
- var ESCROW_DEPOSIT_ABI2 = [
36731
- {
36732
- type: "function",
36733
- name: "depositNative",
36734
- stateMutability: "payable",
36735
- inputs: [{ name: "account", type: "address" }],
36736
- outputs: []
36737
- },
36738
- {
36739
- type: "function",
36740
- name: "depositToken",
36741
- stateMutability: "nonpayable",
36742
- inputs: [
36743
- { name: "account", type: "address" },
36744
- { name: "token", type: "address" },
36745
- { name: "amount", type: "uint256" }
36746
- ],
36747
- outputs: []
36748
- }
36749
- ];
36750
- var NATIVE_ASSET_ADDRESS = "0x0000000000000000000000000000000000000000";
36751
- var EscrowWithdrawalLifecycleError = class extends Error {
36752
- constructor(httpStatus, result) {
36753
- super(result.error);
36754
- this.httpStatus = httpStatus;
36755
- this.result = result;
36756
- }
36757
- httpStatus;
36758
- result;
36759
- name = "EscrowWithdrawalLifecycleError";
36760
- };
36761
- var EscrowWithdrawalRejectionError = class extends Error {
36762
- constructor(httpStatus, result) {
36763
- super(result.error);
36764
- this.httpStatus = httpStatus;
36765
- this.result = result;
36766
- }
36767
- httpStatus;
36768
- result;
36769
- name = "EscrowWithdrawalRejectionError";
36770
- };
36771
- function createEscrowGatewayClient(baseUrl) {
36772
- const base = baseUrl.replace(/\/+$/, "");
36773
- async function throwOnError(res, context) {
36774
- if (!res.ok) {
36775
- let detail = "";
36776
- try {
36777
- const body = await res.json();
36778
- if (body.error) detail = `: ${body.error}`;
36779
- } catch {
36780
- }
36781
- throw new Error(
36782
- `Escrow gateway error (${context}): ${res.status} ${res.statusText}${detail}`
36783
- );
36784
- }
36785
- }
36786
- async function throwOnWithdrawError(res) {
36787
- if (res.ok) return;
36788
- let body;
36789
- try {
36790
- body = await res.json();
36791
- } catch {
36792
- throw new Error(
36793
- `Escrow gateway error (POST /v1/escrow/withdraw): ${res.status} ${res.statusText}`
36794
- );
36795
- }
36796
- if (isEscrowWithdrawalFailureResult(body)) {
36797
- throw new EscrowWithdrawalLifecycleError(res.status, body);
36798
- }
36799
- if (isEscrowWithdrawalRejectedResult(body)) {
36800
- throw new EscrowWithdrawalRejectionError(res.status, body);
36801
- }
36802
- const error = getGatewayErrorMessage(body);
36803
- throw new Error(
36804
- `Escrow gateway error (POST /v1/escrow/withdraw): ${res.status} ${res.statusText}${error ? `: ${error}` : ""}`
36805
- );
36806
- }
36807
- return {
36808
- async submitDeposit({ txHash }) {
36809
- const res = await fetch(`${base}/v1/escrow/deposit`, {
36810
- method: "POST",
36811
- headers: { "Content-Type": "application/json" },
36812
- body: JSON.stringify({ txHash })
36813
- });
36814
- if (res.status !== 200 && res.status !== 202) {
36815
- await throwOnError(res, "POST /v1/escrow/deposit");
36816
- }
36817
- return res.json();
36818
- },
36819
- async getEscrowBalance(account) {
36820
- const res = await fetch(
36821
- `${base}/v1/escrow/balance?account=${encodeURIComponent(account)}`
36822
- );
36823
- await throwOnError(res, "GET /v1/escrow/balance");
36824
- return res.json();
36825
- },
36826
- async syncEscrowBalance(account) {
36827
- const res = await fetch(
36828
- `${base}/v1/escrow/balance/sync?account=${encodeURIComponent(account)}`,
36829
- { method: "POST" }
36830
- );
36831
- await throwOnError(res, "POST /v1/escrow/balance/sync");
36832
- return res.json();
36833
- },
36834
- async payForOp({
36835
- payerAddress,
36836
- opType,
36837
- opId,
36838
- asset,
36839
- amount,
36840
- paymentNonce,
36841
- signature,
36842
- accessRecord
36843
- }) {
36844
- const res = await fetch(`${base}/v1/escrow/pay`, {
36845
- method: "POST",
36846
- headers: {
36847
- "Content-Type": "application/json",
36848
- Authorization: `Web3Signed ${signature}`
36849
- },
36850
- body: JSON.stringify({
36851
- payerAddress,
36852
- opType,
36853
- opId,
36854
- asset,
36855
- amount,
36856
- paymentNonce,
36857
- ...accessRecord ? { accessRecord } : {}
36858
- })
36859
- });
36860
- await throwOnError(res, "POST /v1/escrow/pay");
36861
- return res.json();
36862
- },
36863
- async withdraw({
36864
- account,
36865
- asset,
36866
- amount,
36867
- withdrawNonce,
36868
- deadline,
36869
- signature
36870
- }) {
36871
- const res = await fetch(`${base}/v1/escrow/withdraw`, {
36872
- method: "POST",
36873
- headers: {
36874
- "Content-Type": "application/json",
36875
- Authorization: `Web3Signed ${signature}`
36876
- },
36877
- body: JSON.stringify({
36878
- account,
36879
- asset,
36880
- amount,
36881
- withdrawNonce,
36882
- deadline
36883
- })
36884
- });
36885
- await throwOnWithdrawError(res);
36886
- return res.json();
36887
- },
36888
- async getWithdrawNonce(account) {
36889
- const res = await fetch(
36890
- `${base}/v1/escrow/withdraw/nonce?account=${encodeURIComponent(account)}`,
36891
- { cache: "no-store" }
36892
- );
36893
- await throwOnError(res, "GET /v1/escrow/withdraw/nonce");
36894
- const body = await res.json();
36895
- if (!isWithdrawNonceResponse(body, account)) {
36896
- throw new Error(
36897
- "GET /v1/escrow/withdraw/nonce: invalid response structure"
36898
- );
36899
- }
36900
- return body;
36901
- }
36902
- };
36903
- }
36904
- function getGatewayErrorMessage(body) {
36905
- if (typeof body === "object" && body !== null && "error" in body && typeof body.error === "string") {
36906
- return body.error;
36907
- }
36908
- return void 0;
36909
- }
36910
- function isEscrowWithdrawalFailureResult(body) {
36911
- if (typeof body !== "object" || body === null) return false;
36912
- const value = body;
36913
- return value.success === false && (value.status === "retryable" || value.status === "reorged" || value.status === "failed") && typeof value.error === "string" && isAddressHex(value.account) && isAddressHex(value.asset) && isUint256Decimal(value.amount) && isUint256Decimal(value.withdrawNonce) && isUint256Decimal(value.deadline) && (isHash(value.txHash) || value.txHash === null) && (!("blockNumber" in value) || isBlockNumber(value.blockNumber));
36914
- }
36915
- function isEscrowWithdrawalRejectedResult(body) {
36916
- if (typeof body !== "object" || body === null) return false;
36917
- const value = body;
36918
- return value.success === false && value.status === "rejected" && isWithdrawalRejectionCode(value.code) && typeof value.error === "string" && isAddressHex(value.account) && isAddressHex(value.asset) && isUint256Decimal(value.amount) && isUint256Decimal(value.withdrawNonce) && isUint256Decimal(value.deadline) && optionalUint256Decimal(value.balance) && optionalUint256Decimal(value.authorizedAmount) && optionalUint256Decimal(value.withdrawingAmount) && optionalUint256Decimal(value.availableAmount) && optionalUint256Decimal(value.requestedAmount) && optionalUint256Decimal(value.minimumAmount);
36919
- }
36920
- function isWithdrawalRejectionCode(value) {
36921
- return value === "below_minimum" || value === "deadline_too_far" || value === "expired" || value === "insufficient_available" || value === "stale_nonce";
36922
- }
36923
- function optionalUint256Decimal(value) {
36924
- return value === void 0 || isUint256Decimal(value);
36925
- }
36926
- function isAddressHex(value) {
36927
- return typeof value === "string" && isHex3(value, { strict: true }) && value.length === 42;
36928
- }
36929
- function isHash(value) {
36930
- return typeof value === "string" && isHex3(value, { strict: true }) && value.length === 66;
36931
- }
36932
- function isUint256Decimal(value) {
36933
- if (typeof value !== "string" || value.length === 0 || value.length > 78) {
36934
- return false;
36935
- }
36936
- if (!/^(0|[1-9]\d*)$/.test(value)) return false;
36937
- return BigInt(value) <= 2n ** 256n - 1n;
36938
- }
36939
- function isBlockNumber(value) {
36940
- return value === null || isUint256Decimal(value);
36941
- }
36942
- function isWithdrawNonceResponse(body, requestedAccount) {
36943
- if (typeof body !== "object" || body === null) return false;
36944
- const value = body;
36945
- if (value.success !== true) return false;
36946
- if (!isAddressHex(value.account)) return false;
36947
- if (value.account.toLowerCase() !== requestedAccount.toLowerCase())
36948
- return false;
36949
- if (typeof value.chainId !== "string") return false;
36950
- if (!/^(0|[1-9]\d*)$/.test(value.chainId)) return false;
36951
- const isLastNull = value.lastWithdrawNonce === null;
36952
- const lastNonceValid = isLastNull || isUint256Decimal(value.lastWithdrawNonce);
36953
- if (!lastNonceValid) return false;
36954
- if (!isUint256Decimal(value.nextWithdrawNonce)) return false;
36955
- if (isLastNull) {
36956
- return value.nextWithdrawNonce === "1";
36957
- }
36958
- const lastNonce = BigInt(value.lastWithdrawNonce);
36959
- const nextNonce = BigInt(value.nextWithdrawNonce);
36960
- const expectedNextNonce = lastNonce + 1n;
36961
- if (expectedNextNonce > 2n ** 256n - 1n) return false;
36962
- return nextNonce === expectedNextNonce;
36963
- }
36964
-
36965
37390
  // src/direct/escrow-payment.ts
36966
37391
  var GRANT_OP_TYPE = "grant";
36967
37392
  var DATA_ACCESS_OP_TYPE = "data_access";
@@ -37198,7 +37623,7 @@ async function authorizeEscrowPayment(params) {
37198
37623
  }
37199
37624
 
37200
37625
  // src/direct/personal-server-read.ts
37201
- import { PaymentRequiredError, PersonalServerReadError } from "./direct/errors.js";
37626
+ import { PaymentRequiredError as PaymentRequiredError2, PersonalServerReadError } from "./direct/errors.js";
37202
37627
  import { DataPointDeletedError as DataPointDeletedError4 } from "./errors.js";
37203
37628
  function asRecord2(value) {
37204
37629
  return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
@@ -37515,7 +37940,7 @@ export {
37515
37940
  ENCLAVE_IDENTITY_EVIDENCE_VERSION,
37516
37941
  ENCLAVE_TRUST_ANCHORS,
37517
37942
  ENCLAVE_WALLET_PURPOSE,
37518
- ESCROW_DEPOSIT_ABI2 as ESCROW_DEPOSIT_ABI,
37943
+ ESCROW_DEPOSIT_ABI,
37519
37944
  EscrowWithdrawalLifecycleError,
37520
37945
  EscrowWithdrawalRejectionError,
37521
37946
  ExpiredTokenError2 as ExpiredTokenError,