@unlink-xyz/react 0.1.5 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9042,9 +9042,9 @@ function genBech32(encoding) {
9042
9042
  }
9043
9043
  var bech32m = /* @__PURE__ */ genBech32("bech32m");
9044
9044
  var VERSION = 1;
9045
- var LIMIT = 127;
9045
+ var LIMIT = 130;
9046
9046
  var ALL_CHAINS = "ffffffffffffffff";
9047
- var PREFIX = "0zk";
9047
+ var PREFIX = "unlink";
9048
9048
  var SALT = new TextEncoder().encode("unlink");
9049
9049
  function xorWithSalt(hex2) {
9050
9050
  const bytes2 = Hex.toBytes(hex2);
@@ -9162,7 +9162,7 @@ function parseZkAddress(value) {
9162
9162
  };
9163
9163
  } catch (err) {
9164
9164
  throw new ValidationError(
9165
- `Invalid ZK address (expected 0zk1... format): ${err instanceof Error ? err.message : "unknown error"}`
9165
+ `Invalid ZK address (expected unlink1... format): ${err instanceof Error ? err.message : "unknown error"}`
9166
9166
  );
9167
9167
  }
9168
9168
  }
@@ -35647,29 +35647,41 @@ function createJsonHttpClient(baseUrl, deps) {
35647
35647
  fetch: fetchImpl,
35648
35648
  // Disable ky's automatic error throwing to prevent browser DevTools
35649
35649
  // from logging expected 404s as network errors
35650
- throwHttpErrors: false
35650
+ throwHttpErrors: false,
35651
+ retry: 0
35651
35652
  });
35653
+ const RETRYABLE_STATUSES = [502, 503, 504];
35654
+ const MAX_RETRIES = 3;
35655
+ const BASE_DELAY_MS = 500;
35652
35656
  return {
35653
35657
  async request(opts) {
35654
35658
  let res;
35655
- try {
35656
- res = await api(opts.path.replace(/^\//, ""), {
35657
- method: opts.method,
35658
- searchParams: opts.query,
35659
- json: opts.json,
35660
- body: opts.body,
35661
- headers: opts.headers,
35662
- signal: opts.signal
35663
- });
35664
- } catch (err) {
35665
- if (err instanceof TimeoutError) {
35666
- throw new HttpError("HTTP timeout", 408, null);
35659
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
35660
+ try {
35661
+ res = await api(opts.path.replace(/^\//, ""), {
35662
+ method: opts.method,
35663
+ searchParams: opts.query,
35664
+ json: opts.json,
35665
+ body: opts.body,
35666
+ headers: opts.headers,
35667
+ signal: opts.signal
35668
+ });
35669
+ } catch (err) {
35670
+ if (err instanceof TimeoutError) {
35671
+ throw new HttpError("HTTP timeout", 408, null);
35672
+ }
35673
+ throw new HttpError(
35674
+ err instanceof Error ? err.message : "Network error",
35675
+ 0,
35676
+ null
35677
+ );
35667
35678
  }
35668
- throw new HttpError(
35669
- err instanceof Error ? err.message : "Network error",
35670
- 0,
35671
- null
35672
- );
35679
+ if (RETRYABLE_STATUSES.includes(res.status) && attempt < MAX_RETRIES) {
35680
+ const delay2 = BASE_DELAY_MS * 2 ** attempt + Math.random() * 200;
35681
+ await new Promise((r2) => setTimeout(r2, delay2));
35682
+ continue;
35683
+ }
35684
+ break;
35673
35685
  }
35674
35686
  if (!res.ok) {
35675
35687
  const body = await readErrorBodySafe(res);
@@ -35871,63 +35883,85 @@ var Runtime = {
35871
35883
  }
35872
35884
  };
35873
35885
  var CONFIG_URL = "https://config.unlink.xyz/networks.json";
35874
- function parseRequiredString(env22, field, value) {
35886
+ function parseRequiredString(chain2, field, value) {
35875
35887
  if (typeof value !== "string" || value.trim().length === 0) {
35876
35888
  throw new InitializationError(
35877
- `Invalid SDK config for ${env22}: ${field} must be a non-empty string`
35889
+ `Invalid SDK config for ${chain2}: ${field} must be a non-empty string`
35878
35890
  );
35879
35891
  }
35880
35892
  return value.trim();
35881
35893
  }
35882
- function parseOptionalString(env22, field, value) {
35894
+ function parseOptionalString(chain2, field, value) {
35883
35895
  if (value === void 0) return void 0;
35884
35896
  if (typeof value !== "string" || value.trim().length === 0) {
35885
35897
  throw new InitializationError(
35886
- `Invalid SDK config for ${env22}: ${field} must be a non-empty string when provided`
35898
+ `Invalid SDK config for ${chain2}: ${field} must be a non-empty string when provided`
35887
35899
  );
35888
35900
  }
35889
35901
  return value.trim();
35890
35902
  }
35891
- function parseEnvironmentConfig(env22, value) {
35903
+ function parseRequiredChainId(chain2, value) {
35904
+ if (typeof value !== "number" || !Number.isInteger(value) || value <= 0) {
35905
+ throw new InitializationError(
35906
+ `Invalid SDK config for ${chain2}: chainId must be a positive integer`
35907
+ );
35908
+ }
35909
+ return value;
35910
+ }
35911
+ function parseChainConfig(chain2, value) {
35892
35912
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
35893
35913
  throw new InitializationError(
35894
- `Invalid SDK config for ${env22}: expected object`
35914
+ `Invalid SDK config for ${chain2}: expected object`
35895
35915
  );
35896
35916
  }
35897
35917
  const raw = value;
35918
+ const chainId = parseRequiredChainId(chain2, raw.chainId);
35898
35919
  const gatewayUrl = parseRequiredString(
35899
- env22,
35920
+ chain2,
35900
35921
  "gatewayUrl",
35901
35922
  raw.gatewayUrl
35902
35923
  ).replace(/\/+$/, "");
35903
- const poolAddress = parseRequiredString(env22, "poolAddress", raw.poolAddress);
35924
+ const poolAddress = parseRequiredString(
35925
+ chain2,
35926
+ "poolAddress",
35927
+ raw.poolAddress
35928
+ );
35904
35929
  const artifactVersion = parseRequiredString(
35905
- env22,
35930
+ chain2,
35906
35931
  "artifactVersion",
35907
35932
  raw.artifactVersion
35908
35933
  ).replace(/^\/+|\/+$/g, "");
35934
+ const frostUrl = parseOptionalString(
35935
+ chain2,
35936
+ "frostUrl",
35937
+ raw.frostUrl
35938
+ )?.replace(/\/+$/, "");
35909
35939
  const artifactBaseUrl = parseOptionalString(
35910
- env22,
35940
+ chain2,
35911
35941
  "artifactBaseUrl",
35912
35942
  raw.artifactBaseUrl
35913
35943
  )?.replace(/\/+$/, "");
35914
35944
  return {
35945
+ chainId,
35915
35946
  gatewayUrl,
35947
+ ...frostUrl !== void 0 ? { frostUrl } : {},
35916
35948
  poolAddress,
35917
35949
  artifactVersion,
35918
35950
  ...artifactBaseUrl !== void 0 ? { artifactBaseUrl } : { artifactBaseUrl: DEFAULT_ARTIFACT_BASE_URL }
35919
35951
  };
35920
35952
  }
35921
- async function fetchEnvironmentConfig(env22) {
35953
+ async function fetchChainConfig(chain2) {
35922
35954
  const res = await fetch(CONFIG_URL);
35923
35955
  if (!res.ok) {
35924
35956
  throw new InitializationError(`Failed to fetch SDK config: ${res.status}`);
35925
35957
  }
35926
35958
  const config22 = await res.json();
35927
- if (!config22[env22]) {
35928
- throw new InitializationError(`Unknown environment: ${env22}`);
35959
+ if (!config22[chain2]) {
35960
+ throw new InitializationError(
35961
+ `Unknown chain: "${chain2}". Supported chains: ${Object.keys(config22).join(", ")}`
35962
+ );
35929
35963
  }
35930
- return parseEnvironmentConfig(env22, config22[env22]);
35964
+ return parseChainConfig(chain2, config22[chain2]);
35931
35965
  }
35932
35966
  function createServiceConfig(gatewayUrl) {
35933
35967
  const baseUrl = gatewayUrl.replace(/\/+$/, "");
@@ -53316,6 +53350,114 @@ var circuits_default = {
53316
53350
  template: "JoinSplit",
53317
53351
  pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53318
53352
  params: [5, 2, 16]
53353
+ },
53354
+ joinsplit_1x3_16: {
53355
+ file: "joinsplit",
53356
+ template: "JoinSplit",
53357
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53358
+ params: [1, 3, 16]
53359
+ },
53360
+ joinsplit_4x3_16: {
53361
+ file: "joinsplit",
53362
+ template: "JoinSplit",
53363
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53364
+ params: [4, 3, 16]
53365
+ },
53366
+ joinsplit_5x3_16: {
53367
+ file: "joinsplit",
53368
+ template: "JoinSplit",
53369
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53370
+ params: [5, 3, 16]
53371
+ },
53372
+ joinsplit_6x1_16: {
53373
+ file: "joinsplit",
53374
+ template: "JoinSplit",
53375
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53376
+ params: [6, 1, 16]
53377
+ },
53378
+ joinsplit_6x2_16: {
53379
+ file: "joinsplit",
53380
+ template: "JoinSplit",
53381
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53382
+ params: [6, 2, 16]
53383
+ },
53384
+ joinsplit_6x3_16: {
53385
+ file: "joinsplit",
53386
+ template: "JoinSplit",
53387
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53388
+ params: [6, 3, 16]
53389
+ },
53390
+ joinsplit_7x1_16: {
53391
+ file: "joinsplit",
53392
+ template: "JoinSplit",
53393
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53394
+ params: [7, 1, 16]
53395
+ },
53396
+ joinsplit_7x2_16: {
53397
+ file: "joinsplit",
53398
+ template: "JoinSplit",
53399
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53400
+ params: [7, 2, 16]
53401
+ },
53402
+ joinsplit_7x3_16: {
53403
+ file: "joinsplit",
53404
+ template: "JoinSplit",
53405
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53406
+ params: [7, 3, 16]
53407
+ },
53408
+ joinsplit_8x1_16: {
53409
+ file: "joinsplit",
53410
+ template: "JoinSplit",
53411
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53412
+ params: [8, 1, 16]
53413
+ },
53414
+ joinsplit_8x2_16: {
53415
+ file: "joinsplit",
53416
+ template: "JoinSplit",
53417
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53418
+ params: [8, 2, 16]
53419
+ },
53420
+ joinsplit_8x3_16: {
53421
+ file: "joinsplit",
53422
+ template: "JoinSplit",
53423
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53424
+ params: [8, 3, 16]
53425
+ },
53426
+ joinsplit_9x1_16: {
53427
+ file: "joinsplit",
53428
+ template: "JoinSplit",
53429
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53430
+ params: [9, 1, 16]
53431
+ },
53432
+ joinsplit_9x2_16: {
53433
+ file: "joinsplit",
53434
+ template: "JoinSplit",
53435
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53436
+ params: [9, 2, 16]
53437
+ },
53438
+ joinsplit_9x3_16: {
53439
+ file: "joinsplit",
53440
+ template: "JoinSplit",
53441
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53442
+ params: [9, 3, 16]
53443
+ },
53444
+ joinsplit_10x1_16: {
53445
+ file: "joinsplit",
53446
+ template: "JoinSplit",
53447
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53448
+ params: [10, 1, 16]
53449
+ },
53450
+ joinsplit_10x2_16: {
53451
+ file: "joinsplit",
53452
+ template: "JoinSplit",
53453
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53454
+ params: [10, 2, 16]
53455
+ },
53456
+ joinsplit_10x3_16: {
53457
+ file: "joinsplit",
53458
+ template: "JoinSplit",
53459
+ pubs: ["merkleRoot", "boundParamsHash", "nullifiers", "commitmentsOut"],
53460
+ params: [10, 3, 16]
53319
53461
  }
53320
53462
  };
53321
53463
  var registry = {};
@@ -53331,7 +53473,7 @@ var SUPPORTED_CIRCUITS = Object.keys(CIRCUIT_REGISTRY);
53331
53473
  function getCircuitConfig(inputs, outputs) {
53332
53474
  return CIRCUIT_REGISTRY[`${inputs}x${outputs}`];
53333
53475
  }
53334
- var MAX_ARTIFACT_CACHE_ENTRIES = 8;
53476
+ var MAX_ARTIFACT_CACHE_ENTRIES = 16;
53335
53477
  var artifactCache = /* @__PURE__ */ new Map();
53336
53478
  function selectCircuit(inputs, outputs) {
53337
53479
  const config22 = getCircuitConfig(inputs, outputs);
@@ -55640,6 +55782,16 @@ function createAdapterService(deps) {
55640
55782
  const reshieldSpecs = params.reshields.map(
55641
55783
  (reshield, i) => normalizeReshieldSpec(reshield, i)
55642
55784
  );
55785
+ const seenReshieldTokens = /* @__PURE__ */ new Set();
55786
+ for (const r2 of reshieldSpecs) {
55787
+ const lower = r2.token.toLowerCase();
55788
+ if (seenReshieldTokens.has(lower)) {
55789
+ throw new AdapterError(
55790
+ `duplicate reshield token ${r2.token}; each reshield must target a unique token`
55791
+ );
55792
+ }
55793
+ seenReshieldTokens.add(lower);
55794
+ }
55643
55795
  const account = overrides?.account ?? await deps.requireActiveAccount();
55644
55796
  const signer = overrides?.signer ?? deps.requireSigner(account);
55645
55797
  const nowSeconds = BigInt(Math.floor(nowImpl() / 1e3));
@@ -56536,34 +56688,37 @@ var UnlinkWallet = class _UnlinkWallet {
56536
56688
  * Create a new UnlinkWallet instance.
56537
56689
  *
56538
56690
  * Handles all initialization internally:
56539
- * - Resolves environment config (if using `environment` instead of explicit URLs)
56691
+ * - Resolves chain config (if using `chain` instead of explicit URLs)
56540
56692
  * - Auto-detects storage (IndexedDB in browser) and rng (crypto.getRandomValues)
56541
56693
  * - Runs schema migration via `initCore()`
56542
56694
  * - Creates the internal SDK
56543
56695
  */
56544
56696
  static async create(config22) {
56697
+ let chainId;
56545
56698
  let gatewayUrl;
56546
56699
  let poolAddress;
56547
56700
  let proverConfig = config22.prover;
56548
- if ("gatewayUrl" in config22) {
56701
+ if ("chain" in config22) {
56702
+ const chainConfig = await fetchChainConfig(config22.chain);
56703
+ chainId = chainConfig.chainId;
56704
+ gatewayUrl = chainConfig.gatewayUrl;
56705
+ poolAddress = config22.poolAddress ?? chainConfig.poolAddress;
56706
+ proverConfig = {
56707
+ artifactSource: {
56708
+ baseUrl: config22.prover?.artifactSource?.baseUrl ?? chainConfig.artifactBaseUrl,
56709
+ version: config22.prover?.artifactSource?.version ?? chainConfig.artifactVersion,
56710
+ preferLocalFiles: config22.prover?.artifactSource?.preferLocalFiles
56711
+ }
56712
+ };
56713
+ } else {
56714
+ chainId = config22.chainId;
56549
56715
  gatewayUrl = config22.gatewayUrl;
56550
56716
  poolAddress = config22.poolAddress;
56551
56717
  if (typeof window !== "undefined" && !config22.prover?.artifactSource?.version) {
56552
56718
  throw new InitializationError(
56553
- "prover.artifactSource.version is required in browser when using explicit gatewayUrl mode. Use environment mode or provide a pinned artifact version."
56719
+ "prover.artifactSource.version is required in browser when using explicit gatewayUrl mode. Use chain mode or provide a pinned artifact version."
56554
56720
  );
56555
56721
  }
56556
- } else {
56557
- const envConfig = await fetchEnvironmentConfig(config22.environment);
56558
- gatewayUrl = envConfig.gatewayUrl;
56559
- poolAddress = config22.poolAddress ?? envConfig.poolAddress;
56560
- proverConfig = {
56561
- artifactSource: {
56562
- baseUrl: config22.prover?.artifactSource?.baseUrl ?? envConfig.artifactBaseUrl,
56563
- version: config22.prover?.artifactSource?.version ?? envConfig.artifactVersion,
56564
- preferLocalFiles: config22.prover?.artifactSource?.preferLocalFiles
56565
- }
56566
- };
56567
56722
  }
56568
56723
  const storage = config22.storage ?? detectStorage();
56569
56724
  const rng = config22.rng ?? defaultRng;
@@ -56572,14 +56727,14 @@ var UnlinkWallet = class _UnlinkWallet {
56572
56727
  const sdk = createWalletSDK(
56573
56728
  { core, fetch: fetchImpl },
56574
56729
  {
56575
- chainId: config22.chainId,
56730
+ chainId,
56576
56731
  gatewayUrl,
56577
56732
  chainRpcUrl: config22.chainRpcUrl,
56578
56733
  prover: proverConfig,
56579
56734
  autoSync: config22.autoSync
56580
56735
  }
56581
56736
  );
56582
- return new _UnlinkWallet(sdk, config22.chainId, poolAddress);
56737
+ return new _UnlinkWallet(sdk, chainId, poolAddress);
56583
56738
  }
56584
56739
  // ===== Seed Lifecycle =====
56585
56740
  /** Seed management (create, import, export, delete mnemonic). */
@@ -56935,8 +57090,10 @@ var initialState = {
56935
57090
  accounts: [],
56936
57091
  activeAccount: null,
56937
57092
  activeAccountIndex: null,
57093
+ chainId: null,
56938
57094
  notes: [],
56939
57095
  balances: {},
57096
+ burners: [],
56940
57097
  pendingDeposits: [],
56941
57098
  pendingTransfers: [],
56942
57099
  pendingWithdrawals: [],
@@ -56954,14 +57111,15 @@ function convertNotes(noteRecords) {
56954
57111
  }
56955
57112
  function UnlinkProvider({
56956
57113
  children,
56957
- chainId,
56958
57114
  poolAddress,
56959
57115
  syncInterval = 5e3,
56960
57116
  autoSync = true,
56961
- gatewayUrl,
56962
- environment,
56963
- prover
57117
+ prover,
57118
+ ...configProps
56964
57119
  }) {
57120
+ const chain2 = "chain" in configProps ? configProps.chain : void 0;
57121
+ const chainId = "chainId" in configProps ? configProps.chainId : void 0;
57122
+ const gatewayUrl = "gatewayUrl" in configProps ? configProps.gatewayUrl : void 0;
56965
57123
  const [state, setState] = useState(initialState);
56966
57124
  const walletRef = useRef(null);
56967
57125
  const proverKey = JSON.stringify(prover ?? null);
@@ -56991,13 +57149,13 @@ function UnlinkProvider({
56991
57149
  }
56992
57150
  }, []);
56993
57151
  useEffect(() => {
56994
- if (!gatewayUrl && !environment) {
57152
+ if (!chain2 && !gatewayUrl) {
56995
57153
  const configError = new ValidationError(
56996
- "Either gatewayUrl or environment is required"
57154
+ "Either chain or gatewayUrl is required"
56997
57155
  );
56998
57156
  setState((prev2) => ({
56999
57157
  ...prev2,
57000
- status: "Error: Either gatewayUrl or environment is required",
57158
+ status: "Error: Either chain or gatewayUrl is required",
57001
57159
  error: createUnlinkError(configError, "init")
57002
57160
  }));
57003
57161
  return;
@@ -57011,14 +57169,13 @@ function UnlinkProvider({
57011
57169
  status: "Initializing SDK..."
57012
57170
  }));
57013
57171
  const wallet = await UnlinkWallet.create(
57014
- gatewayUrl ? {
57015
- chainId,
57016
- gatewayUrl,
57172
+ chain2 ? {
57173
+ chain: chain2,
57017
57174
  poolAddress,
57018
57175
  ...prover ? { prover } : {}
57019
57176
  } : {
57020
57177
  chainId,
57021
- environment,
57178
+ gatewayUrl,
57022
57179
  poolAddress,
57023
57180
  ...prover ? { prover } : {}
57024
57181
  }
@@ -57059,6 +57216,7 @@ function UnlinkProvider({
57059
57216
  accounts,
57060
57217
  activeAccount,
57061
57218
  activeAccountIndex,
57219
+ chainId: wallet.chainId,
57062
57220
  notes,
57063
57221
  balances,
57064
57222
  ready: true,
@@ -57069,7 +57227,7 @@ function UnlinkProvider({
57069
57227
  wallet.startAutoSync(syncInterval);
57070
57228
  }
57071
57229
  unsubscribe = wallet.on((event) => {
57072
- if (event.type === "notes-updated" && event.chainId === chainId) {
57230
+ if (event.type === "notes-updated" && event.chainId === wallet.chainId) {
57073
57231
  setState((prev2) => ({ ...prev2, syncError: null }));
57074
57232
  void refreshState(wallet);
57075
57233
  }
@@ -57103,13 +57261,13 @@ function UnlinkProvider({
57103
57261
  walletRef.current?.stopAutoSync();
57104
57262
  };
57105
57263
  }, [
57264
+ chain2,
57106
57265
  chainId,
57107
57266
  autoSync,
57108
57267
  syncInterval,
57109
57268
  refreshState,
57110
57269
  refreshAccounts,
57111
57270
  gatewayUrl,
57112
- environment,
57113
57271
  poolAddress,
57114
57272
  proverKey
57115
57273
  ]);
@@ -57157,6 +57315,7 @@ function UnlinkProvider({
57157
57315
  accounts,
57158
57316
  activeAccount,
57159
57317
  activeAccountIndex,
57318
+ burners: [],
57160
57319
  busy: false,
57161
57320
  status: accounts.length > 0 ? "Wallet imported" : "Wallet imported - create an account",
57162
57321
  syncError: null,
@@ -57191,6 +57350,7 @@ function UnlinkProvider({
57191
57350
  activeAccountIndex: null,
57192
57351
  notes: [],
57193
57352
  balances: {},
57353
+ burners: [],
57194
57354
  busy: false,
57195
57355
  status: "Wallet cleared",
57196
57356
  syncError: null,
@@ -57283,54 +57443,60 @@ function UnlinkProvider({
57283
57443
  throw err;
57284
57444
  }
57285
57445
  }, []);
57286
- const send = useCallback(async (params) => {
57287
- const wallet = walletRef.current;
57288
- if (!wallet) throw new Error("SDK not initialized");
57289
- if (params.length === 0) {
57290
- throw new Error("At least one transfer is required");
57291
- }
57292
- setState((prev2) => ({
57293
- ...prev2,
57294
- busy: true,
57295
- status: params.length > 1 ? `Sending (${params.length} transfers)...` : "Sending..."
57296
- }));
57297
- try {
57298
- const result = await wallet.transfer({
57299
- transfers: params.map((t) => ({
57300
- token: t.token,
57301
- recipient: t.recipient,
57302
- amount: t.amount
57303
- }))
57304
- });
57305
- setState((prev2) => ({
57306
- ...prev2,
57307
- busy: false,
57308
- status: params.length > 1 ? `Transfer submitted (${params.length} transfers)` : "Transfer submitted",
57309
- pendingTransfers: [
57310
- ...prev2.pendingTransfers,
57311
- ...params.map((t, i) => ({
57312
- txId: `${result.relayId}-${i}`,
57313
- status: "pending",
57314
- chainId: wallet.chainId,
57315
- token: t.token,
57316
- amount: t.amount,
57317
- recipient: t.recipient,
57318
- startedAt: Date.now()
57319
- }))
57320
- ],
57321
- error: null
57322
- }));
57323
- return result;
57324
- } catch (err) {
57446
+ const send = useCallback(
57447
+ async (params, overrides) => {
57448
+ const wallet = walletRef.current;
57449
+ if (!wallet) throw new Error("SDK not initialized");
57450
+ if (params.length === 0) {
57451
+ throw new Error("At least one transfer is required");
57452
+ }
57325
57453
  setState((prev2) => ({
57326
57454
  ...prev2,
57327
- busy: false,
57328
- status: `Error: ${err instanceof Error ? err.message : "Unknown"}`,
57329
- error: createUnlinkError(err, "send")
57455
+ busy: true,
57456
+ status: params.length > 1 ? `Sending (${params.length} transfers)...` : "Sending..."
57330
57457
  }));
57331
- throw err;
57332
- }
57333
- }, []);
57458
+ try {
57459
+ const result = await wallet.transfer(
57460
+ {
57461
+ transfers: params.map((t) => ({
57462
+ token: t.token,
57463
+ recipient: t.recipient,
57464
+ amount: t.amount
57465
+ }))
57466
+ },
57467
+ overrides
57468
+ );
57469
+ setState((prev2) => ({
57470
+ ...prev2,
57471
+ busy: false,
57472
+ status: params.length > 1 ? `Transfer submitted (${params.length} transfers)` : "Transfer submitted",
57473
+ pendingTransfers: [
57474
+ ...prev2.pendingTransfers,
57475
+ ...params.map((t, i) => ({
57476
+ txId: `${result.relayId}-${i}`,
57477
+ status: "pending",
57478
+ chainId: wallet.chainId,
57479
+ token: t.token,
57480
+ amount: t.amount,
57481
+ recipient: t.recipient,
57482
+ startedAt: Date.now()
57483
+ }))
57484
+ ],
57485
+ error: null
57486
+ }));
57487
+ return result;
57488
+ } catch (err) {
57489
+ setState((prev2) => ({
57490
+ ...prev2,
57491
+ busy: false,
57492
+ status: `Error: ${err instanceof Error ? err.message : "Unknown"}`,
57493
+ error: createUnlinkError(err, "send")
57494
+ }));
57495
+ throw err;
57496
+ }
57497
+ },
57498
+ []
57499
+ );
57334
57500
  const planTransfer = useCallback(async (params) => {
57335
57501
  const wallet = walletRef.current;
57336
57502
  if (!wallet) throw new Error("SDK not initialized");
@@ -57342,33 +57508,36 @@ function UnlinkProvider({
57342
57508
  }))
57343
57509
  });
57344
57510
  }, []);
57345
- const executeTransfer = useCallback(async (plans) => {
57346
- const wallet = walletRef.current;
57347
- if (!wallet) throw new Error("SDK not initialized");
57348
- setState((prev2) => ({
57349
- ...prev2,
57350
- busy: true,
57351
- status: "Executing transfer..."
57352
- }));
57353
- try {
57354
- const result = await wallet.executeTransfer(plans);
57355
- setState((prev2) => ({
57356
- ...prev2,
57357
- busy: false,
57358
- status: "Transfer executed",
57359
- error: null
57360
- }));
57361
- return result;
57362
- } catch (err) {
57511
+ const executeTransfer = useCallback(
57512
+ async (plans, overrides) => {
57513
+ const wallet = walletRef.current;
57514
+ if (!wallet) throw new Error("SDK not initialized");
57363
57515
  setState((prev2) => ({
57364
57516
  ...prev2,
57365
- busy: false,
57366
- status: `Error: ${err instanceof Error ? err.message : "Unknown"}`,
57367
- error: createUnlinkError(err, "executeTransfer")
57517
+ busy: true,
57518
+ status: "Executing transfer..."
57368
57519
  }));
57369
- throw err;
57370
- }
57371
- }, []);
57520
+ try {
57521
+ const result = await wallet.executeTransfer(plans, overrides);
57522
+ setState((prev2) => ({
57523
+ ...prev2,
57524
+ busy: false,
57525
+ status: "Transfer executed",
57526
+ error: null
57527
+ }));
57528
+ return result;
57529
+ } catch (err) {
57530
+ setState((prev2) => ({
57531
+ ...prev2,
57532
+ busy: false,
57533
+ status: `Error: ${err instanceof Error ? err.message : "Unknown"}`,
57534
+ error: createUnlinkError(err, "executeTransfer")
57535
+ }));
57536
+ throw err;
57537
+ }
57538
+ },
57539
+ []
57540
+ );
57372
57541
  const requestDeposit = useCallback(
57373
57542
  async (params) => {
57374
57543
  const wallet = walletRef.current;
@@ -57425,7 +57594,7 @@ function UnlinkProvider({
57425
57594
  []
57426
57595
  );
57427
57596
  const requestWithdraw = useCallback(
57428
- async (params) => {
57597
+ async (params, overrides) => {
57429
57598
  const wallet = walletRef.current;
57430
57599
  if (!wallet) throw new Error("SDK not initialized");
57431
57600
  if (params.length === 0) {
@@ -57437,13 +57606,16 @@ function UnlinkProvider({
57437
57606
  status: params.length > 1 ? `Processing withdrawal (${params.length} tokens)...` : "Withdrawing..."
57438
57607
  }));
57439
57608
  try {
57440
- const result = await wallet.withdraw({
57441
- withdrawals: params.map((w) => ({
57442
- token: w.token,
57443
- amount: w.amount,
57444
- recipient: w.recipient
57445
- }))
57446
- });
57609
+ const result = await wallet.withdraw(
57610
+ {
57611
+ withdrawals: params.map((w) => ({
57612
+ token: w.token,
57613
+ amount: w.amount,
57614
+ recipient: w.recipient
57615
+ }))
57616
+ },
57617
+ overrides
57618
+ );
57447
57619
  setState((prev2) => ({
57448
57620
  ...prev2,
57449
57621
  busy: false,
@@ -57475,6 +57647,36 @@ function UnlinkProvider({
57475
57647
  },
57476
57648
  []
57477
57649
  );
57650
+ const executeAdapter = useCallback(
57651
+ async (params) => {
57652
+ const wallet = walletRef.current;
57653
+ if (!wallet) throw new Error("SDK not initialized");
57654
+ setState((prev2) => ({
57655
+ ...prev2,
57656
+ busy: true,
57657
+ status: "Executing adapter..."
57658
+ }));
57659
+ try {
57660
+ const result = await wallet.adapter.execute(params);
57661
+ setState((prev2) => ({
57662
+ ...prev2,
57663
+ busy: false,
57664
+ status: "Adapter execution submitted",
57665
+ error: null
57666
+ }));
57667
+ return result;
57668
+ } catch (err) {
57669
+ setState((prev2) => ({
57670
+ ...prev2,
57671
+ busy: false,
57672
+ status: `Error: ${err instanceof Error ? err.message : "Unknown"}`,
57673
+ error: createUnlinkError(err, "executeAdapter")
57674
+ }));
57675
+ throw err;
57676
+ }
57677
+ },
57678
+ []
57679
+ );
57478
57680
  const planWithdraw = useCallback(
57479
57681
  async (params) => {
57480
57682
  const wallet = walletRef.current;
@@ -57489,33 +57691,179 @@ function UnlinkProvider({
57489
57691
  },
57490
57692
  []
57491
57693
  );
57492
- const executeWithdraw = useCallback(async (plans) => {
57694
+ const executeWithdraw = useCallback(
57695
+ async (plans, overrides) => {
57696
+ const wallet = walletRef.current;
57697
+ if (!wallet) throw new Error("SDK not initialized");
57698
+ setState((prev2) => ({
57699
+ ...prev2,
57700
+ busy: true,
57701
+ status: plans.length > 1 ? `Executing withdrawal (${plans.length} tokens)...` : "Executing withdrawal..."
57702
+ }));
57703
+ try {
57704
+ const result = await wallet.executeWithdraw(plans, overrides);
57705
+ setState((prev2) => ({
57706
+ ...prev2,
57707
+ busy: false,
57708
+ status: plans.length > 1 ? `Withdrawal executed (${plans.length} tokens)` : "Withdrawal executed",
57709
+ error: null
57710
+ }));
57711
+ return result;
57712
+ } catch (err) {
57713
+ setState((prev2) => ({
57714
+ ...prev2,
57715
+ busy: false,
57716
+ status: `Error: ${err instanceof Error ? err.message : "Unknown"}`,
57717
+ error: createUnlinkError(err, "executeWithdraw")
57718
+ }));
57719
+ throw err;
57720
+ }
57721
+ },
57722
+ []
57723
+ );
57724
+ const createBurner = useCallback(async (index) => {
57493
57725
  const wallet = walletRef.current;
57494
57726
  if (!wallet) throw new Error("SDK not initialized");
57495
57727
  setState((prev2) => ({
57496
57728
  ...prev2,
57497
57729
  busy: true,
57498
- status: plans.length > 1 ? `Executing withdrawal (${plans.length} tokens)...` : "Executing withdrawal..."
57730
+ status: `Creating burner ${index}...`
57499
57731
  }));
57500
57732
  try {
57501
- const result = await wallet.executeWithdraw(plans);
57733
+ const burner = await wallet.burner.addressOf(index);
57502
57734
  setState((prev2) => ({
57503
57735
  ...prev2,
57736
+ burners: [
57737
+ ...prev2.burners.filter((existing) => existing.index !== burner.index),
57738
+ burner
57739
+ ],
57504
57740
  busy: false,
57505
- status: plans.length > 1 ? `Withdrawal executed (${plans.length} tokens)` : "Withdrawal executed",
57741
+ status: `Burner ${index} ready`,
57506
57742
  error: null
57507
57743
  }));
57508
- return result;
57744
+ return burner;
57509
57745
  } catch (err) {
57510
57746
  setState((prev2) => ({
57511
57747
  ...prev2,
57512
57748
  busy: false,
57513
57749
  status: `Error: ${err instanceof Error ? err.message : "Unknown"}`,
57514
- error: createUnlinkError(err, "executeWithdraw")
57750
+ error: createUnlinkError(err, "createBurner")
57515
57751
  }));
57516
57752
  throw err;
57517
57753
  }
57518
57754
  }, []);
57755
+ const removeBurner = useCallback((index) => {
57756
+ setState((prev2) => ({
57757
+ ...prev2,
57758
+ burners: prev2.burners.filter((burner) => burner.index !== index)
57759
+ }));
57760
+ }, []);
57761
+ const burnerSend = useCallback(
57762
+ async (index, tx) => {
57763
+ const wallet = walletRef.current;
57764
+ if (!wallet) throw new Error("SDK not initialized");
57765
+ setState((prev2) => ({
57766
+ ...prev2,
57767
+ busy: true,
57768
+ status: "Sending burner transaction..."
57769
+ }));
57770
+ try {
57771
+ const result = await wallet.burner.send(index, tx);
57772
+ setState((prev2) => ({
57773
+ ...prev2,
57774
+ busy: false,
57775
+ status: "Burner transaction sent",
57776
+ error: null
57777
+ }));
57778
+ return result;
57779
+ } catch (err) {
57780
+ setState((prev2) => ({
57781
+ ...prev2,
57782
+ busy: false,
57783
+ status: `Error: ${err instanceof Error ? err.message : "Unknown"}`,
57784
+ error: createUnlinkError(err, "burnerSend")
57785
+ }));
57786
+ throw err;
57787
+ }
57788
+ },
57789
+ []
57790
+ );
57791
+ const burnerFund = useCallback(
57792
+ async (index, params) => {
57793
+ const wallet = walletRef.current;
57794
+ if (!wallet) throw new Error("SDK not initialized");
57795
+ setState((prev2) => ({
57796
+ ...prev2,
57797
+ busy: true,
57798
+ status: "Funding burner..."
57799
+ }));
57800
+ try {
57801
+ const result = await wallet.burner.fund(index, params);
57802
+ setState((prev2) => ({
57803
+ ...prev2,
57804
+ busy: false,
57805
+ status: "Burner funded",
57806
+ error: null
57807
+ }));
57808
+ return result;
57809
+ } catch (err) {
57810
+ setState((prev2) => ({
57811
+ ...prev2,
57812
+ busy: false,
57813
+ status: `Error: ${err instanceof Error ? err.message : "Unknown"}`,
57814
+ error: createUnlinkError(err, "burnerFund")
57815
+ }));
57816
+ throw err;
57817
+ }
57818
+ },
57819
+ []
57820
+ );
57821
+ const burnerSweepToPool = useCallback(
57822
+ async (index, params) => {
57823
+ const wallet = walletRef.current;
57824
+ if (!wallet) throw new Error("SDK not initialized");
57825
+ setState((prev2) => ({
57826
+ ...prev2,
57827
+ busy: true,
57828
+ status: "Sweeping burner to pool..."
57829
+ }));
57830
+ try {
57831
+ const result = await wallet.burner.sweepToPool(index, params);
57832
+ setState((prev2) => ({
57833
+ ...prev2,
57834
+ busy: false,
57835
+ status: "Burner sweep submitted",
57836
+ error: null
57837
+ }));
57838
+ return result;
57839
+ } catch (err) {
57840
+ setState((prev2) => ({
57841
+ ...prev2,
57842
+ busy: false,
57843
+ status: `Error: ${err instanceof Error ? err.message : "Unknown"}`,
57844
+ error: createUnlinkError(err, "burnerSweepToPool")
57845
+ }));
57846
+ throw err;
57847
+ }
57848
+ },
57849
+ []
57850
+ );
57851
+ const burnerGetTokenBalance = useCallback(
57852
+ async (address, token) => {
57853
+ const wallet = walletRef.current;
57854
+ if (!wallet) throw new Error("SDK not initialized");
57855
+ return wallet.burner.getTokenBalance(address, token);
57856
+ },
57857
+ []
57858
+ );
57859
+ const burnerGetBalance = useCallback(
57860
+ async (address) => {
57861
+ const wallet = walletRef.current;
57862
+ if (!wallet) throw new Error("SDK not initialized");
57863
+ return wallet.burner.getBalance(address);
57864
+ },
57865
+ []
57866
+ );
57519
57867
  const refresh = useCallback(async () => {
57520
57868
  const wallet = walletRef.current;
57521
57869
  if (!wallet) return;
@@ -57631,7 +57979,6 @@ function UnlinkProvider({
57631
57979
  const value = useMemo(
57632
57980
  () => ({
57633
57981
  ...state,
57634
- chainId,
57635
57982
  // Wallet actions
57636
57983
  createWallet,
57637
57984
  importWallet,
@@ -57648,8 +57995,18 @@ function UnlinkProvider({
57648
57995
  requestDeposit,
57649
57996
  // Withdraw actions
57650
57997
  requestWithdraw,
57998
+ // Adapter actions
57999
+ executeAdapter,
57651
58000
  planWithdraw,
57652
58001
  executeWithdraw,
58002
+ // Burner actions
58003
+ createBurner,
58004
+ removeBurner,
58005
+ burnerSend,
58006
+ burnerFund,
58007
+ burnerSweepToPool,
58008
+ burnerGetTokenBalance,
58009
+ burnerGetBalance,
57653
58010
  // Sync actions
57654
58011
  refresh,
57655
58012
  forceResync,
@@ -57661,7 +58018,6 @@ function UnlinkProvider({
57661
58018
  }),
57662
58019
  [
57663
58020
  state,
57664
- chainId,
57665
58021
  createWallet,
57666
58022
  importWallet,
57667
58023
  exportMnemonic,
@@ -57673,8 +58029,16 @@ function UnlinkProvider({
57673
58029
  executeTransfer,
57674
58030
  requestDeposit,
57675
58031
  requestWithdraw,
58032
+ executeAdapter,
57676
58033
  planWithdraw,
57677
58034
  executeWithdraw,
58035
+ createBurner,
58036
+ removeBurner,
58037
+ burnerSend,
58038
+ burnerFund,
58039
+ burnerSweepToPool,
58040
+ burnerGetTokenBalance,
58041
+ burnerGetBalance,
57678
58042
  refresh,
57679
58043
  forceResync,
57680
58044
  clearError,
@@ -57836,7 +58200,7 @@ function useOperationMutation(operation) {
57836
58200
  const [isError2, setIsError] = useState4(false);
57837
58201
  const pendingRef = useRef3(false);
57838
58202
  const generationRef = useRef3(0);
57839
- const mutate = useCallback4(
58203
+ const execute = useCallback4(
57840
58204
  async (input) => {
57841
58205
  if (pendingRef.current) {
57842
58206
  throw new Error("Operation already in progress");
@@ -57879,7 +58243,7 @@ function useOperationMutation(operation) {
57879
58243
  setIsSuccess(false);
57880
58244
  setIsError(false);
57881
58245
  }, []);
57882
- return { mutate, data, isPending, isSuccess, isError: isError2, error, reset };
58246
+ return { execute, data, isPending, isSuccess, isError: isError2, error, reset };
57883
58247
  }
57884
58248
 
57885
58249
  // src/useDeposit.ts
@@ -57894,22 +58258,76 @@ function useDeposit() {
57894
58258
 
57895
58259
  // src/useTransfer.ts
57896
58260
  import { useCallback as useCallback6 } from "react";
57897
- function useTransfer() {
58261
+ function useTransfer(overrides) {
57898
58262
  const { send } = useUnlink();
57899
- const op = useCallback6((params) => send(params), [send]);
58263
+ const op = useCallback6(
58264
+ (params) => send(params, overrides),
58265
+ [send, overrides]
58266
+ );
57900
58267
  return useOperationMutation(op);
57901
58268
  }
57902
58269
 
57903
58270
  // src/useWithdraw.ts
57904
58271
  import { useCallback as useCallback7 } from "react";
57905
- function useWithdraw() {
58272
+ function useWithdraw(overrides) {
57906
58273
  const { requestWithdraw } = useUnlink();
57907
58274
  const op = useCallback7(
57908
- (params) => requestWithdraw(params),
57909
- [requestWithdraw]
58275
+ (params) => requestWithdraw(params, overrides),
58276
+ [requestWithdraw, overrides]
57910
58277
  );
57911
58278
  return useOperationMutation(op);
57912
58279
  }
58280
+
58281
+ // src/useAdapter.ts
58282
+ import { useCallback as useCallback8 } from "react";
58283
+ function useAdapter() {
58284
+ const { executeAdapter } = useUnlink();
58285
+ const op = useCallback8(
58286
+ (params) => executeAdapter(params),
58287
+ [executeAdapter]
58288
+ );
58289
+ return useOperationMutation(op);
58290
+ }
58291
+
58292
+ // src/useBurner.ts
58293
+ import { useCallback as useCallback9 } from "react";
58294
+ function useBurner() {
58295
+ const {
58296
+ burners,
58297
+ createBurner,
58298
+ removeBurner,
58299
+ burnerSend,
58300
+ burnerFund,
58301
+ burnerSweepToPool,
58302
+ burnerGetTokenBalance,
58303
+ burnerGetBalance
58304
+ } = useUnlink();
58305
+ const sendOp = useCallback9(
58306
+ (input) => burnerSend(input.index, input.tx),
58307
+ [burnerSend]
58308
+ );
58309
+ const fundOp = useCallback9(
58310
+ (input) => burnerFund(input.index, input.params),
58311
+ [burnerFund]
58312
+ );
58313
+ const sweepOp = useCallback9(
58314
+ (input) => burnerSweepToPool(input.index, input.params),
58315
+ [burnerSweepToPool]
58316
+ );
58317
+ const send = useOperationMutation(sendOp);
58318
+ const fund = useOperationMutation(fundOp);
58319
+ const sweepToPool = useOperationMutation(sweepOp);
58320
+ return {
58321
+ burners,
58322
+ createBurner,
58323
+ removeBurner,
58324
+ send,
58325
+ fund,
58326
+ sweepToPool,
58327
+ getTokenBalance: burnerGetTokenBalance,
58328
+ getBalance: burnerGetBalance
58329
+ };
58330
+ }
57913
58331
  export {
57914
58332
  CONFIRMATION_POLL_INTERVAL_MS,
57915
58333
  DEFAULT_CONFIRMATION_TIMEOUT_MS,
@@ -57926,6 +58344,8 @@ export {
57926
58344
  parseZkAddress,
57927
58345
  randomHex,
57928
58346
  shortenHex,
58347
+ useAdapter,
58348
+ useBurner,
57929
58349
  useDeposit,
57930
58350
  useOperationMutation,
57931
58351
  useTransfer,