@unlink-xyz/core 0.1.5 → 0.1.7-canary.252b8ea

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.
Files changed (38) hide show
  1. package/dist/account/account.d.ts +1 -1
  2. package/dist/account/account.d.ts.map +1 -1
  3. package/dist/browser/index.js +476 -215
  4. package/dist/browser/index.js.map +1 -1
  5. package/dist/browser/wallet/index.js +427 -213
  6. package/dist/browser/wallet/index.js.map +1 -1
  7. package/dist/clients/http.d.ts.map +1 -1
  8. package/dist/config.d.ts +20 -8
  9. package/dist/config.d.ts.map +1 -1
  10. package/dist/index.d.ts +3 -3
  11. package/dist/index.d.ts.map +1 -1
  12. package/dist/index.js +399 -138
  13. package/dist/index.js.map +1 -1
  14. package/dist/transactions/adapter.d.ts +34 -1
  15. package/dist/transactions/adapter.d.ts.map +1 -1
  16. package/dist/transactions/index.d.ts +1 -1
  17. package/dist/transactions/index.d.ts.map +1 -1
  18. package/dist/tsconfig.tsbuildinfo +1 -1
  19. package/dist/utils/async.js.map +1 -1
  20. package/dist/utils/validators.d.ts +1 -1
  21. package/dist/wallet/adapter.d.ts +2 -2
  22. package/dist/wallet/adapter.d.ts.map +1 -1
  23. package/dist/wallet/burner/service.d.ts +1 -0
  24. package/dist/wallet/burner/service.d.ts.map +1 -1
  25. package/dist/wallet/burner/types.d.ts +2 -2
  26. package/dist/wallet/burner/types.d.ts.map +1 -1
  27. package/dist/wallet/index.d.ts +2 -2
  28. package/dist/wallet/index.d.ts.map +1 -1
  29. package/dist/wallet/index.js +350 -136
  30. package/dist/wallet/index.js.map +1 -1
  31. package/dist/wallet/sdk.d.ts +8 -9
  32. package/dist/wallet/sdk.d.ts.map +1 -1
  33. package/dist/wallet/types.d.ts +61 -52
  34. package/dist/wallet/types.d.ts.map +1 -1
  35. package/dist/wallet/{unlink-wallet.d.ts → unlink.d.ts} +44 -38
  36. package/dist/wallet/unlink.d.ts.map +1 -0
  37. package/package.json +1 -1
  38. package/dist/wallet/unlink-wallet.d.ts.map +0 -1
@@ -1827,63 +1827,110 @@ var Runtime = {
1827
1827
 
1828
1828
  // config.ts
1829
1829
  var CONFIG_URL = "https://config.unlink.xyz/networks.json";
1830
- function parseRequiredString(env, field, value) {
1830
+ function parseRequiredString(chain, field, value) {
1831
1831
  if (typeof value !== "string" || value.trim().length === 0) {
1832
1832
  throw new InitializationError(
1833
- `Invalid SDK config for ${env}: ${field} must be a non-empty string`
1833
+ `Invalid SDK config for ${chain}: ${field} must be a non-empty string`
1834
1834
  );
1835
1835
  }
1836
1836
  return value.trim();
1837
1837
  }
1838
- function parseOptionalString(env, field, value) {
1838
+ function parseOptionalString(chain, field, value) {
1839
1839
  if (value === void 0) return void 0;
1840
1840
  if (typeof value !== "string" || value.trim().length === 0) {
1841
1841
  throw new InitializationError(
1842
- `Invalid SDK config for ${env}: ${field} must be a non-empty string when provided`
1842
+ `Invalid SDK config for ${chain}: ${field} must be a non-empty string when provided`
1843
1843
  );
1844
1844
  }
1845
1845
  return value.trim();
1846
1846
  }
1847
- function parseEnvironmentConfig(env, value) {
1847
+ function parseRequiredChainId(chain, value) {
1848
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
1849
+ throw new InitializationError(
1850
+ `Invalid SDK config for ${chain}: chainId must be a positive integer`
1851
+ );
1852
+ }
1853
+ return value;
1854
+ }
1855
+ function parseChainConfig(chain, value) {
1848
1856
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
1849
1857
  throw new InitializationError(
1850
- `Invalid SDK config for ${env}: expected object`
1858
+ `Invalid SDK config for ${chain}: expected object`
1851
1859
  );
1852
1860
  }
1853
1861
  const raw = value;
1862
+ const chainId = parseRequiredChainId(chain, raw.chainId);
1854
1863
  const gatewayUrl = parseRequiredString(
1855
- env,
1864
+ chain,
1856
1865
  "gatewayUrl",
1857
1866
  raw.gatewayUrl
1858
1867
  ).replace(/\/+$/, "");
1859
- const poolAddress = parseRequiredString(env, "poolAddress", raw.poolAddress);
1868
+ const poolAddress = parseRequiredString(
1869
+ chain,
1870
+ "poolAddress",
1871
+ raw.poolAddress
1872
+ );
1860
1873
  const artifactVersion = parseRequiredString(
1861
- env,
1874
+ chain,
1862
1875
  "artifactVersion",
1863
1876
  raw.artifactVersion
1864
1877
  ).replace(/^\/+|\/+$/g, "");
1878
+ const adapterAddress = parseOptionalString(
1879
+ chain,
1880
+ "adapterAddress",
1881
+ raw.adapterAddress
1882
+ );
1883
+ const frostUrl = parseOptionalString(
1884
+ chain,
1885
+ "frostUrl",
1886
+ raw.frostUrl
1887
+ )?.replace(/\/+$/, "");
1865
1888
  const artifactBaseUrl = parseOptionalString(
1866
- env,
1889
+ chain,
1867
1890
  "artifactBaseUrl",
1868
1891
  raw.artifactBaseUrl
1869
1892
  )?.replace(/\/+$/, "");
1893
+ let tokenAddresses;
1894
+ if (raw.tokenAddresses !== void 0) {
1895
+ if (raw.tokenAddresses === null || typeof raw.tokenAddresses !== "object" || Array.isArray(raw.tokenAddresses)) {
1896
+ throw new InitializationError(
1897
+ `Invalid SDK config for ${chain}: tokenAddresses must be an object`
1898
+ );
1899
+ }
1900
+ tokenAddresses = {};
1901
+ for (const [name, addr] of Object.entries(
1902
+ raw.tokenAddresses
1903
+ )) {
1904
+ tokenAddresses[name] = parseRequiredString(
1905
+ chain,
1906
+ `tokenAddresses.${name}`,
1907
+ addr
1908
+ );
1909
+ }
1910
+ }
1870
1911
  return {
1912
+ chainId,
1871
1913
  gatewayUrl,
1914
+ ...frostUrl !== void 0 ? { frostUrl } : {},
1872
1915
  poolAddress,
1916
+ ...adapterAddress !== void 0 ? { adapterAddress } : {},
1873
1917
  artifactVersion,
1874
- ...artifactBaseUrl !== void 0 ? { artifactBaseUrl } : { artifactBaseUrl: DEFAULT_ARTIFACT_BASE_URL }
1918
+ ...artifactBaseUrl !== void 0 ? { artifactBaseUrl } : { artifactBaseUrl: DEFAULT_ARTIFACT_BASE_URL },
1919
+ ...tokenAddresses !== void 0 ? { tokenAddresses } : {}
1875
1920
  };
1876
1921
  }
1877
- async function fetchEnvironmentConfig(env) {
1922
+ async function fetchChainConfig(chain) {
1878
1923
  const res = await fetch(CONFIG_URL);
1879
1924
  if (!res.ok) {
1880
1925
  throw new InitializationError(`Failed to fetch SDK config: ${res.status}`);
1881
1926
  }
1882
1927
  const config = await res.json();
1883
- if (!config[env]) {
1884
- throw new InitializationError(`Unknown environment: ${env}`);
1928
+ if (!config[chain]) {
1929
+ throw new InitializationError(
1930
+ `Unknown chain: "${chain}". Supported chains: ${Object.keys(config).join(", ")}`
1931
+ );
1885
1932
  }
1886
- return parseEnvironmentConfig(env, config[env]);
1933
+ return parseChainConfig(chain, config[chain]);
1887
1934
  }
1888
1935
  function createServiceConfig(gatewayUrl) {
1889
1936
  const baseUrl = gatewayUrl.replace(/\/+$/, "");
@@ -2220,9 +2267,9 @@ var Hex = class _Hex {
2220
2267
 
2221
2268
  // keys/address.ts
2222
2269
  var VERSION = 1;
2223
- var LIMIT = 127;
2270
+ var LIMIT = 130;
2224
2271
  var ALL_CHAINS = "ffffffffffffffff";
2225
- var PREFIX = "0zk";
2272
+ var PREFIX = "unlink";
2226
2273
  var SALT = new TextEncoder().encode("unlink");
2227
2274
  function xorWithSalt(hex) {
2228
2275
  const bytes = Hex.toBytes(hex);
@@ -3970,29 +4017,41 @@ function createJsonHttpClient(baseUrl, deps) {
3970
4017
  fetch: fetchImpl,
3971
4018
  // Disable ky's automatic error throwing to prevent browser DevTools
3972
4019
  // from logging expected 404s as network errors
3973
- throwHttpErrors: false
4020
+ throwHttpErrors: false,
4021
+ retry: 0
3974
4022
  });
4023
+ const RETRYABLE_STATUSES = [502, 503, 504];
4024
+ const MAX_RETRIES = 3;
4025
+ const BASE_DELAY_MS = 500;
3975
4026
  return {
3976
4027
  async request(opts) {
3977
4028
  let res;
3978
- try {
3979
- res = await api(opts.path.replace(/^\//, ""), {
3980
- method: opts.method,
3981
- searchParams: opts.query,
3982
- json: opts.json,
3983
- body: opts.body,
3984
- headers: opts.headers,
3985
- signal: opts.signal
3986
- });
3987
- } catch (err) {
3988
- if (err instanceof TimeoutError) {
3989
- throw new HttpError("HTTP timeout", 408, null);
4029
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
4030
+ try {
4031
+ res = await api(opts.path.replace(/^\//, ""), {
4032
+ method: opts.method,
4033
+ searchParams: opts.query,
4034
+ json: opts.json,
4035
+ body: opts.body,
4036
+ headers: opts.headers,
4037
+ signal: opts.signal
4038
+ });
4039
+ } catch (err) {
4040
+ if (err instanceof TimeoutError) {
4041
+ throw new HttpError("HTTP timeout", 408, null);
4042
+ }
4043
+ throw new HttpError(
4044
+ err instanceof Error ? err.message : "Network error",
4045
+ 0,
4046
+ null
4047
+ );
3990
4048
  }
3991
- throw new HttpError(
3992
- err instanceof Error ? err.message : "Network error",
3993
- 0,
3994
- null
3995
- );
4049
+ if (RETRYABLE_STATUSES.includes(res.status) && attempt < MAX_RETRIES) {
4050
+ const delay = BASE_DELAY_MS * 2 ** attempt + Math.random() * 200;
4051
+ await new Promise((r2) => setTimeout(r2, delay));
4052
+ continue;
4053
+ }
4054
+ break;
3996
4055
  }
3997
4056
  if (!res.ok) {
3998
4057
  const body = await readErrorBodySafe(res);
@@ -4210,7 +4269,7 @@ function parseZkAddress(value) {
4210
4269
  };
4211
4270
  } catch (err) {
4212
4271
  throw new ValidationError(
4213
- `Invalid ZK address (expected 0zk1... format): ${err instanceof Error ? err.message : "unknown error"}`
4272
+ `Invalid ZK address (expected unlink1... format): ${err instanceof Error ? err.message : "unknown error"}`
4214
4273
  );
4215
4274
  }
4216
4275
  }
@@ -6206,6 +6265,114 @@ var circuits_default = {
6206
6265
  template: "JoinSplit",
6207
6266
  pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6208
6267
  params: [5, 2, 16]
6268
+ },
6269
+ joinsplit_1x3_16: {
6270
+ file: "joinsplit",
6271
+ template: "JoinSplit",
6272
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6273
+ params: [1, 3, 16]
6274
+ },
6275
+ joinsplit_4x3_16: {
6276
+ file: "joinsplit",
6277
+ template: "JoinSplit",
6278
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6279
+ params: [4, 3, 16]
6280
+ },
6281
+ joinsplit_5x3_16: {
6282
+ file: "joinsplit",
6283
+ template: "JoinSplit",
6284
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6285
+ params: [5, 3, 16]
6286
+ },
6287
+ joinsplit_6x1_16: {
6288
+ file: "joinsplit",
6289
+ template: "JoinSplit",
6290
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6291
+ params: [6, 1, 16]
6292
+ },
6293
+ joinsplit_6x2_16: {
6294
+ file: "joinsplit",
6295
+ template: "JoinSplit",
6296
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6297
+ params: [6, 2, 16]
6298
+ },
6299
+ joinsplit_6x3_16: {
6300
+ file: "joinsplit",
6301
+ template: "JoinSplit",
6302
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6303
+ params: [6, 3, 16]
6304
+ },
6305
+ joinsplit_7x1_16: {
6306
+ file: "joinsplit",
6307
+ template: "JoinSplit",
6308
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6309
+ params: [7, 1, 16]
6310
+ },
6311
+ joinsplit_7x2_16: {
6312
+ file: "joinsplit",
6313
+ template: "JoinSplit",
6314
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6315
+ params: [7, 2, 16]
6316
+ },
6317
+ joinsplit_7x3_16: {
6318
+ file: "joinsplit",
6319
+ template: "JoinSplit",
6320
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6321
+ params: [7, 3, 16]
6322
+ },
6323
+ joinsplit_8x1_16: {
6324
+ file: "joinsplit",
6325
+ template: "JoinSplit",
6326
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6327
+ params: [8, 1, 16]
6328
+ },
6329
+ joinsplit_8x2_16: {
6330
+ file: "joinsplit",
6331
+ template: "JoinSplit",
6332
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6333
+ params: [8, 2, 16]
6334
+ },
6335
+ joinsplit_8x3_16: {
6336
+ file: "joinsplit",
6337
+ template: "JoinSplit",
6338
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6339
+ params: [8, 3, 16]
6340
+ },
6341
+ joinsplit_9x1_16: {
6342
+ file: "joinsplit",
6343
+ template: "JoinSplit",
6344
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6345
+ params: [9, 1, 16]
6346
+ },
6347
+ joinsplit_9x2_16: {
6348
+ file: "joinsplit",
6349
+ template: "JoinSplit",
6350
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6351
+ params: [9, 2, 16]
6352
+ },
6353
+ joinsplit_9x3_16: {
6354
+ file: "joinsplit",
6355
+ template: "JoinSplit",
6356
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6357
+ params: [9, 3, 16]
6358
+ },
6359
+ joinsplit_10x1_16: {
6360
+ file: "joinsplit",
6361
+ template: "JoinSplit",
6362
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6363
+ params: [10, 1, 16]
6364
+ },
6365
+ joinsplit_10x2_16: {
6366
+ file: "joinsplit",
6367
+ template: "JoinSplit",
6368
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6369
+ params: [10, 2, 16]
6370
+ },
6371
+ joinsplit_10x3_16: {
6372
+ file: "joinsplit",
6373
+ template: "JoinSplit",
6374
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
6375
+ params: [10, 3, 16]
6209
6376
  }
6210
6377
  };
6211
6378
 
@@ -6225,7 +6392,7 @@ function getCircuitConfig(inputs, outputs) {
6225
6392
  }
6226
6393
 
6227
6394
  // prover/prover.ts
6228
- var MAX_ARTIFACT_CACHE_ENTRIES = 8;
6395
+ var MAX_ARTIFACT_CACHE_ENTRIES = 16;
6229
6396
  var artifactCache = /* @__PURE__ */ new Map();
6230
6397
  function selectCircuit(inputs, outputs) {
6231
6398
  const config = getCircuitConfig(inputs, outputs);
@@ -8208,26 +8375,34 @@ function normalizeCall2(call, index) {
8208
8375
  value: call.value
8209
8376
  };
8210
8377
  }
8211
- function normalizeInputSpec(input, index) {
8212
- const token = ensureAddress(`inputs[${index}].token`, input.token);
8378
+ function normalizeSpendInput(input, index) {
8379
+ const token = ensureAddress(`spend[${index}].token`, input.token);
8380
+ if (token.toLowerCase() === ETH_TOKEN.toLowerCase()) {
8381
+ throw new AdapterError(
8382
+ `spend[${index}].token: native ETH is not supported in adapter execution`
8383
+ );
8384
+ }
8213
8385
  if (input.amount <= 0n) {
8214
- throw new AdapterError(`inputs[${index}].amount must be greater than zero`);
8386
+ throw new AdapterError(`spend[${index}].amount must be greater than zero`);
8215
8387
  }
8216
8388
  return {
8217
8389
  token,
8218
8390
  amount: input.amount
8219
8391
  };
8220
8392
  }
8221
- function normalizeReshieldSpec(reshield, index) {
8222
- const token = ensureAddress(`reshields[${index}].token`, reshield.token);
8223
- if (reshield.minAmount < 0n) {
8393
+ function normalizeReceiveInput(receive, index) {
8394
+ const token = ensureAddress(`receive[${index}].token`, receive.token);
8395
+ if (token.toLowerCase() === ETH_TOKEN.toLowerCase()) {
8224
8396
  throw new AdapterError(
8225
- `reshields[${index}].minAmount must be non-negative`
8397
+ `receive[${index}].token: native ETH is not supported in adapter execution`
8226
8398
  );
8227
8399
  }
8400
+ if (receive.minAmount < 0n) {
8401
+ throw new AdapterError(`receive[${index}].minAmount must be non-negative`);
8402
+ }
8228
8403
  return {
8229
8404
  token,
8230
- minAmount: reshield.minAmount
8405
+ minAmount: receive.minAmount
8231
8406
  };
8232
8407
  }
8233
8408
  function randomFieldElement(randomBigintFn) {
@@ -8247,32 +8422,42 @@ function createAdapterService(deps) {
8247
8422
  "adapterAddress",
8248
8423
  params.adapterAddress
8249
8424
  );
8250
- if (!params.inputs.length) {
8251
- throw new AdapterError("at least one input token is required");
8425
+ if (!params.spend.length) {
8426
+ throw new AdapterError("at least one spend token is required");
8252
8427
  }
8253
8428
  if (!params.calls.length) {
8254
8429
  throw new AdapterError("at least one adapter call is required");
8255
8430
  }
8256
- if (!params.reshields.length) {
8257
- throw new AdapterError("at least one reshield output is required");
8431
+ if (!params.receive.length) {
8432
+ throw new AdapterError("at least one receive output is required");
8258
8433
  }
8259
- const inputs = params.inputs.map(
8260
- (input, i) => normalizeInputSpec(input, i)
8434
+ const spendInputs = params.spend.map(
8435
+ (input, i) => normalizeSpendInput(input, i)
8261
8436
  );
8262
8437
  const seenTokens = /* @__PURE__ */ new Set();
8263
- for (const input of inputs) {
8438
+ for (const input of spendInputs) {
8264
8439
  const lower = input.token.toLowerCase();
8265
8440
  if (seenTokens.has(lower)) {
8266
8441
  throw new AdapterError(
8267
- `duplicate input token ${input.token}; combine amounts per token instead`
8442
+ `duplicate spend token ${input.token}; combine amounts per token instead`
8268
8443
  );
8269
8444
  }
8270
8445
  seenTokens.add(lower);
8271
8446
  }
8272
8447
  const calls = params.calls.map((call, i) => normalizeCall2(call, i));
8273
- const reshieldSpecs = params.reshields.map(
8274
- (reshield, i) => normalizeReshieldSpec(reshield, i)
8448
+ const receiveSpecs = params.receive.map(
8449
+ (receive, i) => normalizeReceiveInput(receive, i)
8275
8450
  );
8451
+ const seenReceiveTokens = /* @__PURE__ */ new Set();
8452
+ for (const r2 of receiveSpecs) {
8453
+ const lower = r2.token.toLowerCase();
8454
+ if (seenReceiveTokens.has(lower)) {
8455
+ throw new AdapterError(
8456
+ `duplicate receive token ${r2.token}; each receive must target a unique token`
8457
+ );
8458
+ }
8459
+ seenReceiveTokens.add(lower);
8460
+ }
8276
8461
  const account = overrides?.account ?? await deps.requireActiveAccount();
8277
8462
  const signer = overrides?.signer ?? deps.requireSigner(account);
8278
8463
  const nowSeconds = BigInt(Math.floor(nowImpl() / 1e3));
@@ -8281,19 +8466,19 @@ function createAdapterService(deps) {
8281
8466
  throw new AdapterError("deadline must be in the future");
8282
8467
  }
8283
8468
  const executionCalls = calls;
8284
- const reshields = reshieldSpecs.map(
8285
- (reshield) => {
8469
+ const reshields = receiveSpecs.map(
8470
+ (receive) => {
8286
8471
  const random = randomFieldElement(randomBigintImpl);
8287
8472
  const npk = poseidon([account.masterPublicKey, random]);
8288
8473
  return {
8289
8474
  npk,
8290
8475
  random,
8291
- token: reshield.token,
8292
- minAmount: reshield.minAmount
8476
+ token: receive.token,
8477
+ minAmount: receive.minAmount
8293
8478
  };
8294
8479
  }
8295
8480
  );
8296
- const inputTokens = inputs.map((input) => input.token);
8481
+ const inputTokens = spendInputs.map((input) => input.token);
8297
8482
  const nonce = randomFieldElement(randomBigintImpl);
8298
8483
  const adapterDataHash = computeAdapterDataHash({
8299
8484
  calls: executionCalls,
@@ -8310,7 +8495,7 @@ function createAdapterService(deps) {
8310
8495
  });
8311
8496
  const withdrawalPlans = planWithdrawalsImpl(
8312
8497
  notes,
8313
- inputs.map((input) => ({
8498
+ spendInputs.map((input) => ({
8314
8499
  token: input.token,
8315
8500
  amount: input.amount,
8316
8501
  recipient: adapterAddress
@@ -8393,7 +8578,7 @@ function createAdapterService(deps) {
8393
8578
  adapterCalldata,
8394
8579
  historyPreview: {
8395
8580
  kind: "Withdraw",
8396
- amounts: inputs.map((input) => ({
8581
+ amounts: spendInputs.map((input) => ({
8397
8582
  token: input.token,
8398
8583
  delta: (-input.amount).toString()
8399
8584
  }))
@@ -8420,6 +8605,9 @@ import {
8420
8605
  } from "ethers";
8421
8606
  var BIP44_ETH_PREFIX = "m/44'/60'/0'/0";
8422
8607
  var ERC20_BALANCE_OF = "function balanceOf(address) view returns (uint256)";
8608
+ function isNativeToken(token) {
8609
+ return token.toLowerCase() === ETH_TOKEN.toLowerCase();
8610
+ }
8423
8611
  function createBurnerService(deps) {
8424
8612
  const { chainRpcUrl, getMasterSeed, withdrawToAddress, requestDeposit } = deps;
8425
8613
  const provider = new JsonRpcProvider(chainRpcUrl);
@@ -8467,8 +8655,8 @@ function createBurnerService(deps) {
8467
8655
  }
8468
8656
  async function getTokenBalance(address, token) {
8469
8657
  const iface = new Interface4([ERC20_BALANCE_OF]);
8470
- const contract = new Contract(token, iface, provider);
8471
- const bal = await contract.getFunction("balanceOf")(address);
8658
+ const contract2 = new Contract(token, iface, provider);
8659
+ const bal = await contract2.getFunction("balanceOf")(address);
8472
8660
  return BigInt(bal ?? 0);
8473
8661
  }
8474
8662
  async function getBalance(address) {
@@ -8487,6 +8675,12 @@ function createBurnerService(deps) {
8487
8675
  }
8488
8676
  async function sweepToPool(index, params) {
8489
8677
  const { address } = await addressOf(index);
8678
+ const native = isNativeToken(params.token);
8679
+ if (native && params.amount == null) {
8680
+ throw new Error(
8681
+ "amount is required for native ETH sweeps (needed to reserve gas)"
8682
+ );
8683
+ }
8490
8684
  const amount = params.amount ?? await getTokenBalance(address, params.token);
8491
8685
  if (amount === 0n) {
8492
8686
  throw new Error("No token balance to sweep");
@@ -8497,17 +8691,20 @@ function createBurnerService(deps) {
8497
8691
  depositor: address,
8498
8692
  deposits: [{ token: params.token, amount }]
8499
8693
  });
8500
- const erc20Iface = new Interface4([
8501
- "function approve(address spender, uint256 amount)"
8502
- ]);
8503
- const approveData = erc20Iface.encodeFunctionData("approve", [
8504
- params.poolAddress,
8505
- amount
8506
- ]);
8507
- await send(index, { to: params.token, data: approveData });
8694
+ if (!native) {
8695
+ const erc20Iface = new Interface4([
8696
+ "function approve(address spender, uint256 amount)"
8697
+ ]);
8698
+ const approveData = erc20Iface.encodeFunctionData("approve", [
8699
+ params.poolAddress,
8700
+ amount
8701
+ ]);
8702
+ await send(index, { to: params.token, data: approveData });
8703
+ }
8508
8704
  const { txHash } = await send(index, {
8509
8705
  to: depositResult.to,
8510
- data: depositResult.calldata
8706
+ data: depositResult.calldata,
8707
+ value: depositResult.value
8511
8708
  });
8512
8709
  return { txHash };
8513
8710
  }
@@ -9163,28 +9360,31 @@ function createWalletSDK(deps, options) {
9163
9360
  return sdk;
9164
9361
  }
9165
9362
  async function createBrowserWalletSDK(options) {
9363
+ let chainId;
9166
9364
  let gatewayUrl;
9167
9365
  let poolAddress;
9168
9366
  let prover = options.prover;
9169
- if ("gatewayUrl" in options) {
9367
+ if ("chain" in options) {
9368
+ const chainConfig = await fetchChainConfig(options.chain);
9369
+ chainId = chainConfig.chainId;
9370
+ gatewayUrl = chainConfig.gatewayUrl;
9371
+ poolAddress = options.poolAddress ?? chainConfig.poolAddress;
9372
+ prover = {
9373
+ artifactSource: {
9374
+ baseUrl: options.prover?.artifactSource?.baseUrl ?? chainConfig.artifactBaseUrl,
9375
+ version: options.prover?.artifactSource?.version ?? chainConfig.artifactVersion,
9376
+ preferLocalFiles: options.prover?.artifactSource?.preferLocalFiles
9377
+ }
9378
+ };
9379
+ } else {
9380
+ chainId = options.chainId;
9170
9381
  gatewayUrl = options.gatewayUrl;
9171
9382
  poolAddress = options.poolAddress;
9172
9383
  if (typeof window !== "undefined" && !options.prover?.artifactSource?.version) {
9173
9384
  throw new InitializationError(
9174
- "prover.artifactSource.version is required in browser when using explicit gatewayUrl mode. Use environment mode or provide a pinned artifact version."
9385
+ "prover.artifactSource.version is required in browser when using explicit gatewayUrl mode. Use chain mode or provide a pinned artifact version."
9175
9386
  );
9176
9387
  }
9177
- } else {
9178
- const envConfig = await fetchEnvironmentConfig(options.environment);
9179
- gatewayUrl = envConfig.gatewayUrl;
9180
- poolAddress = options.poolAddress ?? envConfig.poolAddress;
9181
- prover = {
9182
- artifactSource: {
9183
- baseUrl: options.prover?.artifactSource?.baseUrl ?? envConfig.artifactBaseUrl,
9184
- version: options.prover?.artifactSource?.version ?? envConfig.artifactVersion,
9185
- preferLocalFiles: options.prover?.artifactSource?.preferLocalFiles
9186
- }
9187
- };
9188
9388
  }
9189
9389
  const storage = createIndexedDbStorage({ name: "unlink-wallet" });
9190
9390
  const rng = (n) => {
@@ -9201,7 +9401,7 @@ async function createBrowserWalletSDK(options) {
9201
9401
  core,
9202
9402
  fetch: globalThis.fetch
9203
9403
  },
9204
- { chainId: options.chainId, gatewayUrl, prover }
9404
+ { chainId, gatewayUrl, prover }
9205
9405
  );
9206
9406
  return {
9207
9407
  sdk,
@@ -9214,51 +9414,63 @@ async function createBrowserWalletSDK(options) {
9214
9414
  };
9215
9415
  }
9216
9416
 
9217
- // wallet/unlink-wallet.ts
9218
- var UnlinkWallet = class _UnlinkWallet {
9417
+ // wallet/unlink.ts
9418
+ var Unlink = class _Unlink {
9219
9419
  /** @internal */
9220
9420
  sdk;
9221
9421
  /** Chain ID this wallet operates on. */
9222
9422
  chainId;
9223
9423
  /** Pool contract address this wallet transacts with. */
9224
9424
  poolAddress;
9225
- constructor(sdk, chainId, poolAddress) {
9425
+ /** Adapter contract address for DeFi operations. */
9426
+ adapterAddress;
9427
+ constructor(sdk, chainId, poolAddress, adapterAddress) {
9226
9428
  this.sdk = sdk;
9227
9429
  this.chainId = chainId;
9228
9430
  this.poolAddress = poolAddress;
9431
+ this.adapterAddress = adapterAddress;
9432
+ this.adapter = {
9433
+ address: adapterAddress
9434
+ };
9229
9435
  }
9230
9436
  /**
9231
- * Create a new UnlinkWallet instance.
9437
+ * Create a new Unlink instance.
9232
9438
  *
9233
9439
  * Handles all initialization internally:
9234
- * - Resolves environment config (if using `environment` instead of explicit URLs)
9440
+ * - Resolves chain config (if using `chain` instead of explicit URLs)
9235
9441
  * - Auto-detects storage (IndexedDB in browser) and rng (crypto.getRandomValues)
9236
9442
  * - Runs schema migration via `initCore()`
9237
9443
  * - Creates the internal SDK
9238
9444
  */
9239
9445
  static async create(config) {
9446
+ let chainId;
9240
9447
  let gatewayUrl;
9241
9448
  let poolAddress;
9449
+ let adapterAddress;
9242
9450
  let proverConfig = config.prover;
9243
- if ("gatewayUrl" in config) {
9451
+ if ("chain" in config) {
9452
+ const chainConfig = await fetchChainConfig(config.chain);
9453
+ chainId = chainConfig.chainId;
9454
+ gatewayUrl = chainConfig.gatewayUrl;
9455
+ poolAddress = config.poolAddress ?? chainConfig.poolAddress;
9456
+ adapterAddress = config.adapterAddress ?? chainConfig.adapterAddress;
9457
+ proverConfig = {
9458
+ artifactSource: {
9459
+ baseUrl: config.prover?.artifactSource?.baseUrl ?? chainConfig.artifactBaseUrl,
9460
+ version: config.prover?.artifactSource?.version ?? chainConfig.artifactVersion,
9461
+ preferLocalFiles: config.prover?.artifactSource?.preferLocalFiles
9462
+ }
9463
+ };
9464
+ } else {
9465
+ chainId = config.chainId;
9244
9466
  gatewayUrl = config.gatewayUrl;
9245
9467
  poolAddress = config.poolAddress;
9468
+ adapterAddress = config.adapterAddress;
9246
9469
  if (typeof window !== "undefined" && !config.prover?.artifactSource?.version) {
9247
9470
  throw new InitializationError(
9248
- "prover.artifactSource.version is required in browser when using explicit gatewayUrl mode. Use environment mode or provide a pinned artifact version."
9471
+ "prover.artifactSource.version is required in browser when using explicit gatewayUrl mode. Use chain mode or provide a pinned artifact version."
9249
9472
  );
9250
9473
  }
9251
- } else {
9252
- const envConfig = await fetchEnvironmentConfig(config.environment);
9253
- gatewayUrl = envConfig.gatewayUrl;
9254
- poolAddress = config.poolAddress ?? envConfig.poolAddress;
9255
- proverConfig = {
9256
- artifactSource: {
9257
- baseUrl: config.prover?.artifactSource?.baseUrl ?? envConfig.artifactBaseUrl,
9258
- version: config.prover?.artifactSource?.version ?? envConfig.artifactVersion,
9259
- preferLocalFiles: config.prover?.artifactSource?.preferLocalFiles
9260
- }
9261
- };
9262
9474
  }
9263
9475
  const storage = config.storage ?? detectStorage();
9264
9476
  const rng = config.rng ?? defaultRng;
@@ -9267,14 +9479,14 @@ var UnlinkWallet = class _UnlinkWallet {
9267
9479
  const sdk = createWalletSDK(
9268
9480
  { core, fetch: fetchImpl },
9269
9481
  {
9270
- chainId: config.chainId,
9482
+ chainId,
9271
9483
  gatewayUrl,
9272
9484
  chainRpcUrl: config.chainRpcUrl,
9273
9485
  prover: proverConfig,
9274
9486
  autoSync: config.autoSync
9275
9487
  }
9276
9488
  );
9277
- return new _UnlinkWallet(sdk, config.chainId, poolAddress);
9489
+ return new _Unlink(sdk, chainId, poolAddress, adapterAddress ?? "");
9278
9490
  }
9279
9491
  // ===== Seed Lifecycle =====
9280
9492
  /** Seed management (create, import, export, delete mnemonic). */
@@ -9305,10 +9517,10 @@ var UnlinkWallet = class _UnlinkWallet {
9305
9517
  return this.sdk.deposit.reconcile(relayId);
9306
9518
  }
9307
9519
  /**
9308
- * Execute a private transfer (1 or more recipients).
9520
+ * Send a private transfer (1 or more recipients).
9309
9521
  * Handles note selection, circuit selection, and proof generation automatically.
9310
9522
  */
9311
- async transfer(params, overrides) {
9523
+ async send(params, overrides) {
9312
9524
  return this.sdk.transfer.send(
9313
9525
  {
9314
9526
  chainId: this.chainId,
@@ -9319,9 +9531,9 @@ var UnlinkWallet = class _UnlinkWallet {
9319
9531
  );
9320
9532
  }
9321
9533
  /**
9322
- * Get a transfer plan without executing (for preview/confirmation UIs).
9534
+ * Get a send plan without executing (for preview/confirmation UIs).
9323
9535
  */
9324
- async planTransfer(params, account) {
9536
+ async planSend(params, account) {
9325
9537
  return this.sdk.transfer.plan(
9326
9538
  {
9327
9539
  chainId: this.chainId,
@@ -9331,8 +9543,8 @@ var UnlinkWallet = class _UnlinkWallet {
9331
9543
  account
9332
9544
  );
9333
9545
  }
9334
- /** Execute a pre-built transfer plan. */
9335
- async executeTransfer(plans, overrides) {
9546
+ /** Execute a pre-built send plan. */
9547
+ async executeSend(plans, overrides) {
9336
9548
  return this.sdk.transfer.execute(
9337
9549
  plans,
9338
9550
  { chainId: this.chainId, poolAddress: this.poolAddress },
@@ -9481,31 +9693,31 @@ var UnlinkWallet = class _UnlinkWallet {
9481
9693
  return this.sdk.burner.getBalance(address);
9482
9694
  }
9483
9695
  };
9484
- // ===== Adapter =====
9696
+ // ===== Interact (Private DeFi) =====
9485
9697
  /**
9486
- * Private DeFi adapter operations.
9487
- * chainId/poolAddress are injected automatically.
9698
+ * Adapter contract address (resolved from config).
9699
+ * Use for building DeFi calls that reference the adapter.
9488
9700
  */
9489
- adapter = {
9490
- /**
9491
- * Execute an atomic unshield -> call(s) -> reshield flow through an adapter.
9492
- */
9493
- execute: (params, opts, overrides) => {
9494
- return this.sdk.adapter.execute(
9495
- {
9496
- chainId: this.chainId,
9497
- poolAddress: this.poolAddress,
9498
- adapterAddress: params.adapterAddress,
9499
- inputs: params.inputs,
9500
- calls: params.calls,
9501
- reshields: params.reshields,
9502
- deadline: params.deadline
9503
- },
9504
- opts,
9505
- overrides
9506
- );
9507
- }
9508
- };
9701
+ adapter;
9702
+ /**
9703
+ * Execute an atomic unshield -> DeFi call(s) -> reshield flow through an adapter.
9704
+ * chainId/poolAddress/adapterAddress are injected automatically.
9705
+ */
9706
+ async interact(params, opts, overrides) {
9707
+ return this.sdk.adapter.execute(
9708
+ {
9709
+ chainId: this.chainId,
9710
+ poolAddress: this.poolAddress,
9711
+ adapterAddress: this.adapterAddress,
9712
+ spend: params.spend,
9713
+ calls: params.calls,
9714
+ receive: params.receive,
9715
+ deadline: params.deadline
9716
+ },
9717
+ opts,
9718
+ overrides
9719
+ );
9720
+ }
9509
9721
  // ===== Advanced =====
9510
9722
  /**
9511
9723
  * Advanced escape hatch for raw JoinSplit transaction building.
@@ -9553,6 +9765,7 @@ var defaultRng = (n) => {
9553
9765
  }
9554
9766
  return globalThis.crypto.getRandomValues(new Uint8Array(n));
9555
9767
  };
9768
+ var UnlinkWallet = Unlink;
9556
9769
 
9557
9770
  // utils/amounts.ts
9558
9771
  function parseAmount(value, decimals) {
@@ -9605,6 +9818,7 @@ export {
9605
9818
  HttpError,
9606
9819
  InitializationError,
9607
9820
  ProofError,
9821
+ Unlink,
9608
9822
  UnlinkWallet,
9609
9823
  ValidationError,
9610
9824
  computeBalances,