@rareprotocol/rare-cli 1.1.0 → 1.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.
package/dist/client.js CHANGED
@@ -17,6 +17,7 @@ var contractAddresses = {
17
17
  sepolia: {
18
18
  factory: getAddress("0x3c7526a0975156299ceef369b8ff3c01cc670523"),
19
19
  auction: getAddress("0xC8Edc7049b233641ad3723D6C60019D1c8771612"),
20
+ rareBridge: getAddress("0xdC168291658f6C5F1D0b33E573c4d289DCA9dD08"),
20
21
  sovereignFactory: getAddress("0x46B2850ba7787734F648A6848b5eDE0815C1F8Bf"),
21
22
  lazySovereignFactory: getAddress("0xc5B8Ad9003673a23d005A6448C74d8955a1a38fA"),
22
23
  rareMinter: getAddress("0xd28Dc0B89104d7BBd902F338a0193fF063617ccE"),
@@ -34,6 +35,7 @@ var contractAddresses = {
34
35
  mainnet: {
35
36
  factory: getAddress("0xAe8E375a268Ed6442bEaC66C6254d6De5AeD4aB1"),
36
37
  auction: getAddress("0x6D7c44773C52D396F43c2D511B81aa168E9a7a42"),
38
+ rareBridge: getAddress("0x88135dd0e7a8a2e42272dda89849a997ce2e83f7"),
37
39
  sovereignFactory: getAddress("0xe980ec62378529d95ba446433f4deb6324129c59"),
38
40
  lazySovereignFactory: getAddress("0xba798BD606d86D207ca2751510173532899117a1"),
39
41
  rareMinter: getAddress("0x5fa112EFeD8297bec0010b312208d223E0cE891E"),
@@ -44,19 +46,27 @@ var contractAddresses = {
44
46
  marketplaceSettings: getAddress("0x61DBF87164d33FD3695256DC8Ba74D3B1d304170"),
45
47
  erc20ApprovalManager: getAddress("0xa837a7eAff154Ab837617Cf7250648D3Ec0A4436"),
46
48
  erc721ApprovalManager: getAddress("0x4bb0Deea6d1A30C601338aAB776d394C2AE5c0F8"),
47
- liquidFactory: getAddress("0xbb4341CFd588a098e9aCE1D224178836426c4a8E"),
49
+ liquidFactory: getAddress("0x25f993C222fE5e891128a782A5168f1C78629540"),
48
50
  swapRouter: getAddress("0xEBd58EdA8408d9EA409f2c2bE8898BD9738f3583"),
49
51
  v4Quoter: getAddress("0x52F0E24D1c21C8A0cB1e5a5dD6198556BD9E1203")
50
52
  },
51
53
  base: {
52
54
  factory: getAddress("0xf776204233bfb52ba0ddff24810cbdbf3dbf94dd"),
53
- auction: getAddress("0x51c36ffb05e17ed80ee5c02fa83d7677c5613de2")
55
+ auction: getAddress("0x51c36ffb05e17ed80ee5c02fa83d7677c5613de2"),
56
+ rareBridge: getAddress("0x3b41e21094611d152a08d3691a70837f1a077dae")
54
57
  },
55
58
  "base-sepolia": {
56
59
  factory: getAddress("0x2b181ae0f1aea6fed75591b04991b1a3f9868d51"),
57
- auction: getAddress("0x1f0c946f0ee87acb268d50ede6c9b4d010af65d2")
60
+ auction: getAddress("0x1f0c946f0ee87acb268d50ede6c9b4d010af65d2"),
61
+ rareBridge: getAddress("0xca491bb62A7730E97F500510132C47633DDD0229")
58
62
  }
59
63
  };
64
+ var ccipChainSelectors = {
65
+ mainnet: 5009297550715157269n,
66
+ sepolia: 16015286601757825753n,
67
+ base: 15971525489660198786n,
68
+ "base-sepolia": 10344971235874465080n
69
+ };
60
70
  var canonicalV4Pools = {
61
71
  sepolia: {
62
72
  rareEthPool: {
@@ -206,6 +216,16 @@ function getCanonicalV4Pools(chain) {
206
216
  }
207
217
  return pools;
208
218
  }
219
+ function getRareBridgeAddress(chain) {
220
+ const address = getContractAddresses(chain).rareBridge;
221
+ if (!address) {
222
+ throw new Error(`RareBridge is not configured on "${chain}". Supported RareBridge chains: mainnet, sepolia, base, base-sepolia.`);
223
+ }
224
+ return address;
225
+ }
226
+ function getCcipChainSelector(chain) {
227
+ return ccipChainSelectors[chain];
228
+ }
209
229
  function isSupportedChain(value) {
210
230
  return supportedChains.some((chain) => chain === value);
211
231
  }
@@ -248,8 +268,12 @@ var RareApiError = class extends Error {
248
268
 
249
269
  // src/data-access/base-url.ts
250
270
  var DEFAULT_RARE_API_BASE_URL = "https://api.superrare.com";
271
+ function normalizeRareApiBaseUrlCandidate(baseUrl) {
272
+ const trimmedBaseUrl = baseUrl?.trim();
273
+ return trimmedBaseUrl === "" ? void 0 : trimmedBaseUrl;
274
+ }
251
275
  function resolveRareApiBaseUrl(baseUrl) {
252
- return process.env.RARE_API_BASE_URL ?? baseUrl ?? DEFAULT_RARE_API_BASE_URL;
276
+ return normalizeRareApiBaseUrlCandidate(process.env.RARE_API_BASE_URL) ?? normalizeRareApiBaseUrlCandidate(baseUrl) ?? DEFAULT_RARE_API_BASE_URL;
253
277
  }
254
278
 
255
279
  // src/data-access/client.ts
@@ -3481,6 +3505,50 @@ var auctionAbi = [
3481
3505
  ];
3482
3506
 
3483
3507
  // src/sdk/approvals-shell.ts
3508
+ var ApprovalSideEffectError = class extends Error {
3509
+ operation;
3510
+ approvals;
3511
+ constructor(params) {
3512
+ super(
3513
+ `${approvalSummary(params.approvals)} before ${params.operation}, but ${params.operation} did not complete. The approval remains valid; retry the operation or revoke approval if it should not remain active.`,
3514
+ { cause: params.cause }
3515
+ );
3516
+ this.name = "ApprovalSideEffectError";
3517
+ this.operation = params.operation;
3518
+ this.approvals = params.approvals;
3519
+ }
3520
+ };
3521
+ async function runWithApprovalSideEffectAlert(params) {
3522
+ try {
3523
+ return await params.run();
3524
+ } catch (error) {
3525
+ const approvals = params.approvals.filter(hasApprovalTxHash);
3526
+ if (approvals.length === 0) {
3527
+ throw error;
3528
+ }
3529
+ throw new ApprovalSideEffectError({
3530
+ operation: params.operation,
3531
+ approvals,
3532
+ cause: error
3533
+ });
3534
+ }
3535
+ }
3536
+ function hasApprovalTxHash(approval) {
3537
+ return approval.approvalTxHash !== void 0;
3538
+ }
3539
+ function approvalSummary(approvals) {
3540
+ const [approval] = approvals;
3541
+ return approvals.length === 1 && approval !== void 0 ? `Approval transaction ${approval.approvalTxHash} was mined (${approvalDetails(approval)})` : `Approval transactions were mined: ${approvals.map((sideEffect) => `${sideEffect.approvalTxHash} (${approvalDetails(sideEffect)})`).join(", ")}`;
3542
+ }
3543
+ function approvalDetails(approval) {
3544
+ if (approval.type === "erc20" || approval.type === "erc20-reset") {
3545
+ return `${approval.type}; token ${approval.target}; spender ${approval.spender ?? "unknown"}`;
3546
+ }
3547
+ if (approval.type === "minter") {
3548
+ return `minter; collection ${approval.target}; minter ${approval.minter ?? "unknown"}`;
3549
+ }
3550
+ return `nft; contract ${approval.target}; operator ${approval.operator ?? "unknown"}`;
3551
+ }
3484
3552
  var approvalAbi = [
3485
3553
  {
3486
3554
  inputs: [{ name: "owner", type: "address" }, { name: "operator", type: "address" }],
@@ -3633,7 +3701,7 @@ async function toTokenAmount(publicClient, token, value, field) {
3633
3701
  }
3634
3702
  async function ensureTokenAllowance(publicClient, walletClient, account, owner, token, spender, amount) {
3635
3703
  if (isAddressEqual4(token, ETH_ADDRESS) || amount === 0n) {
3636
- return;
3704
+ return void 0;
3637
3705
  }
3638
3706
  const allowance = await publicClient.readContract({
3639
3707
  address: token,
@@ -3642,7 +3710,7 @@ async function ensureTokenAllowance(publicClient, walletClient, account, owner,
3642
3710
  args: [owner, spender]
3643
3711
  });
3644
3712
  if (allowance >= amount) {
3645
- return;
3713
+ return void 0;
3646
3714
  }
3647
3715
  const approveTx = await walletClient.writeContract({
3648
3716
  address: token,
@@ -3652,7 +3720,14 @@ async function ensureTokenAllowance(publicClient, walletClient, account, owner,
3652
3720
  account,
3653
3721
  chain: void 0
3654
3722
  });
3655
- await publicClient.waitForTransactionReceipt({ hash: approveTx });
3723
+ await confirmErc20Approval(publicClient, {
3724
+ approvalTxHash: approveTx,
3725
+ currency: token,
3726
+ accountAddress: owner,
3727
+ spenderAddress: spender,
3728
+ requiredAmount: amount
3729
+ });
3730
+ return approveTx;
3656
3731
  }
3657
3732
  var PaymentApprovalRequiredError = class extends Error {
3658
3733
  requiredAmount;
@@ -3725,7 +3800,13 @@ async function preparePaymentAmountForSpender(opts) {
3725
3800
  account,
3726
3801
  chain: void 0
3727
3802
  });
3728
- await publicClient.waitForTransactionReceipt({ hash: approvalTxHash });
3803
+ await confirmErc20Approval(publicClient, {
3804
+ approvalTxHash,
3805
+ currency,
3806
+ accountAddress,
3807
+ spenderAddress,
3808
+ requiredAmount
3809
+ });
3729
3810
  return {
3730
3811
  value: 0n,
3731
3812
  requiredAmount,
@@ -3763,6 +3844,23 @@ async function readAllowance(publicClient, currency, accountAddress, spenderAddr
3763
3844
  args: [accountAddress, spenderAddress]
3764
3845
  });
3765
3846
  }
3847
+ async function confirmErc20Approval(publicClient, params) {
3848
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: params.approvalTxHash });
3849
+ if (receipt.status !== "success") {
3850
+ throw new Error(`ERC20 approval transaction ${params.approvalTxHash} did not succeed.`);
3851
+ }
3852
+ const allowance = await readAllowance(
3853
+ publicClient,
3854
+ params.currency,
3855
+ params.accountAddress,
3856
+ params.spenderAddress
3857
+ );
3858
+ if (allowance < params.requiredAmount) {
3859
+ throw new Error(
3860
+ `ERC20 approval transaction ${params.approvalTxHash} was mined but allowance for spender ${params.spenderAddress} is ${allowance.toString()} raw units, below the required ${params.requiredAmount.toString()} raw units.`
3861
+ );
3862
+ }
3863
+ }
3766
3864
 
3767
3865
  // src/sdk/validation-core.ts
3768
3866
  import { isHex } from "viem";
@@ -4207,6 +4305,11 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
4207
4305
  accountAddress,
4208
4306
  currentUnixTimestamp()
4209
4307
  );
4308
+ const auctionType = await publicClient.readContract({
4309
+ address: addresses.auction,
4310
+ abi: auctionAbi,
4311
+ functionName: plan.auctionType === "scheduled" ? "SCHEDULED_AUCTION" : "COLDIE_AUCTION"
4312
+ });
4210
4313
  const approvalTxHash = await approveNftContractIfNeeded({
4211
4314
  publicClient,
4212
4315
  walletClient,
@@ -4216,30 +4319,37 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
4216
4319
  operator: addresses.auction,
4217
4320
  autoApprove: params.autoApprove
4218
4321
  });
4219
- const auctionType = await publicClient.readContract({
4220
- address: addresses.auction,
4221
- abi: auctionAbi,
4222
- functionName: plan.auctionType === "scheduled" ? "SCHEDULED_AUCTION" : "COLDIE_AUCTION"
4223
- });
4224
- const txHash = await walletClient.writeContract({
4225
- address: addresses.auction,
4226
- abi: auctionAbi,
4227
- functionName: "configureAuction",
4228
- args: [
4229
- auctionType,
4230
- plan.nftAddress,
4231
- plan.tokenId,
4232
- plan.startingPrice,
4233
- plan.currency,
4234
- plan.duration,
4235
- plan.startTime,
4236
- plan.splitAddresses,
4237
- plan.splitRatios
4238
- ],
4239
- account,
4240
- chain: void 0
4322
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
4323
+ operation: "auction create",
4324
+ approvals: [{
4325
+ type: "nft",
4326
+ approvalTxHash,
4327
+ target: plan.nftAddress,
4328
+ operator: addresses.auction
4329
+ }],
4330
+ run: async () => {
4331
+ const targetTxHash = await walletClient.writeContract({
4332
+ address: addresses.auction,
4333
+ abi: auctionAbi,
4334
+ functionName: "configureAuction",
4335
+ args: [
4336
+ auctionType,
4337
+ plan.nftAddress,
4338
+ plan.tokenId,
4339
+ plan.startingPrice,
4340
+ plan.currency,
4341
+ plan.duration,
4342
+ plan.startTime,
4343
+ plan.splitAddresses,
4344
+ plan.splitRatios
4345
+ ],
4346
+ account,
4347
+ chain: void 0
4348
+ });
4349
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
4350
+ return { txHash: targetTxHash, receipt: targetReceipt };
4351
+ }
4241
4352
  });
4242
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
4243
4353
  return {
4244
4354
  txHash,
4245
4355
  receipt,
@@ -4265,22 +4375,34 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
4265
4375
  amount: plan.amount,
4266
4376
  autoApprove: params.autoApprove
4267
4377
  });
4268
- const txHash = await walletClient.writeContract({
4269
- address: addresses.auction,
4270
- abi: auctionAbi,
4271
- functionName: "bid",
4272
- args: [params.contract, plan.tokenId, plan.currency, plan.amount],
4273
- account,
4274
- chain: void 0,
4275
- value: payment.value
4378
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
4379
+ operation: "auction bid",
4380
+ approvals: [{
4381
+ type: "erc20",
4382
+ approvalTxHash: payment.approvalTxHash,
4383
+ target: plan.currency,
4384
+ spender: addresses.auction
4385
+ }],
4386
+ run: async () => {
4387
+ const targetTxHash = await walletClient.writeContract({
4388
+ address: addresses.auction,
4389
+ abi: auctionAbi,
4390
+ functionName: "bid",
4391
+ args: [params.contract, plan.tokenId, plan.currency, plan.amount],
4392
+ account,
4393
+ chain: void 0,
4394
+ value: payment.value
4395
+ });
4396
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
4397
+ return { txHash: targetTxHash, receipt: targetReceipt };
4398
+ }
4276
4399
  });
4277
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
4278
4400
  return { txHash, receipt, approvalTxHash: payment.approvalTxHash };
4279
4401
  },
4280
4402
  async settle(params) {
4281
4403
  const { walletClient, account } = requireWallet(config);
4282
4404
  const plan = planAuctionTokenAction(params);
4283
- const txHash = await walletClient.writeContract({
4405
+ const targetTxHash = await walletClient.writeContract({
4284
4406
  address: addresses.auction,
4285
4407
  abi: auctionAbi,
4286
4408
  functionName: "settleAuction",
@@ -4288,13 +4410,13 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
4288
4410
  account,
4289
4411
  chain: void 0
4290
4412
  });
4291
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
4292
- return { txHash, receipt };
4413
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
4414
+ return { txHash: targetTxHash, receipt: targetReceipt };
4293
4415
  },
4294
4416
  async cancel(params) {
4295
4417
  const { walletClient, account } = requireWallet(config);
4296
4418
  const plan = planAuctionTokenAction(params);
4297
- const txHash = await walletClient.writeContract({
4419
+ const targetTxHash = await walletClient.writeContract({
4298
4420
  address: addresses.auction,
4299
4421
  abi: auctionAbi,
4300
4422
  functionName: "cancelAuction",
@@ -4302,8 +4424,8 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
4302
4424
  account,
4303
4425
  chain: void 0
4304
4426
  });
4305
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
4306
- return { txHash, receipt };
4427
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
4428
+ return { txHash: targetTxHash, receipt: targetReceipt };
4307
4429
  },
4308
4430
  async status(params) {
4309
4431
  const plan = planAuctionTokenAction(params);
@@ -4380,23 +4502,35 @@ function createOfferNamespace(publicClient, config, chain, addresses) {
4380
4502
  amount: plan.amount,
4381
4503
  autoApprove: params.autoApprove
4382
4504
  });
4383
- const txHash = await walletClient.writeContract({
4384
- address: addresses.auction,
4385
- abi: auctionAbi,
4386
- functionName: "offer",
4387
- args: [params.contract, plan.tokenId, plan.currency, plan.amount, false],
4388
- account,
4389
- chain: void 0,
4390
- value: payment.value
4505
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
4506
+ operation: "offer create",
4507
+ approvals: [{
4508
+ type: "erc20",
4509
+ approvalTxHash: payment.approvalTxHash,
4510
+ target: plan.currency,
4511
+ spender: addresses.auction
4512
+ }],
4513
+ run: async () => {
4514
+ const targetTxHash = await walletClient.writeContract({
4515
+ address: addresses.auction,
4516
+ abi: auctionAbi,
4517
+ functionName: "offer",
4518
+ args: [params.contract, plan.tokenId, plan.currency, plan.amount, false],
4519
+ account,
4520
+ chain: void 0,
4521
+ value: payment.value
4522
+ });
4523
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
4524
+ return { txHash: targetTxHash, receipt: targetReceipt };
4525
+ }
4391
4526
  });
4392
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
4393
4527
  return { txHash, receipt, approvalTxHash: payment.approvalTxHash };
4394
4528
  },
4395
4529
  async cancel(params) {
4396
4530
  const { walletClient, account } = requireWallet(config);
4397
4531
  const currency = params.currency === void 0 ? ETH_ADDRESS : resolveCurrencyForSdk(params.currency, chain).address;
4398
4532
  const plan = planOfferCancel({ ...params, currency });
4399
- const txHash = await walletClient.writeContract({
4533
+ const targetTxHash = await walletClient.writeContract({
4400
4534
  address: addresses.auction,
4401
4535
  abi: auctionAbi,
4402
4536
  functionName: "cancelOffer",
@@ -4404,8 +4538,8 @@ function createOfferNamespace(publicClient, config, chain, addresses) {
4404
4538
  account,
4405
4539
  chain: void 0
4406
4540
  });
4407
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
4408
- return { txHash, receipt };
4541
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
4542
+ return { txHash: targetTxHash, receipt: targetReceipt };
4409
4543
  },
4410
4544
  async accept(params) {
4411
4545
  const { walletClient, account, accountAddress } = requireWallet(config);
@@ -4422,22 +4556,34 @@ function createOfferNamespace(publicClient, config, chain, addresses) {
4422
4556
  operator: addresses.auction,
4423
4557
  autoApprove: params.autoApprove
4424
4558
  });
4425
- const txHash = await walletClient.writeContract({
4426
- address: addresses.auction,
4427
- abi: auctionAbi,
4428
- functionName: "acceptOffer",
4429
- args: [
4430
- params.contract,
4431
- plan.tokenId,
4432
- plan.currency,
4433
- plan.amount,
4434
- plan.splitAddresses,
4435
- plan.splitRatios
4436
- ],
4437
- account,
4438
- chain: void 0
4559
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
4560
+ operation: "offer accept",
4561
+ approvals: [{
4562
+ type: "nft",
4563
+ approvalTxHash,
4564
+ target: params.contract,
4565
+ operator: addresses.auction
4566
+ }],
4567
+ run: async () => {
4568
+ const targetTxHash = await walletClient.writeContract({
4569
+ address: addresses.auction,
4570
+ abi: auctionAbi,
4571
+ functionName: "acceptOffer",
4572
+ args: [
4573
+ params.contract,
4574
+ plan.tokenId,
4575
+ plan.currency,
4576
+ plan.amount,
4577
+ plan.splitAddresses,
4578
+ plan.splitRatios
4579
+ ],
4580
+ account,
4581
+ chain: void 0
4582
+ });
4583
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
4584
+ return { txHash: targetTxHash, receipt: targetReceipt };
4585
+ }
4439
4586
  });
4440
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
4441
4587
  return { txHash, receipt, approvalTxHash };
4442
4588
  },
4443
4589
  async status(params) {
@@ -4502,29 +4648,41 @@ function createListingNamespace(publicClient, config, chain, addresses) {
4502
4648
  operator: addresses.auction,
4503
4649
  autoApprove: params.autoApprove
4504
4650
  });
4505
- const txHash = await walletClient.writeContract({
4506
- address: addresses.auction,
4507
- abi: auctionAbi,
4508
- functionName: "setSalePrice",
4509
- args: [
4510
- plan.nftAddress,
4511
- plan.tokenId,
4512
- plan.currency,
4513
- plan.price,
4514
- plan.target,
4515
- plan.splitAddresses,
4516
- plan.splitRatios
4517
- ],
4518
- account,
4519
- chain: void 0
4651
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
4652
+ operation: "listing create",
4653
+ approvals: [{
4654
+ type: "nft",
4655
+ approvalTxHash,
4656
+ target: plan.nftAddress,
4657
+ operator: addresses.auction
4658
+ }],
4659
+ run: async () => {
4660
+ const targetTxHash = await walletClient.writeContract({
4661
+ address: addresses.auction,
4662
+ abi: auctionAbi,
4663
+ functionName: "setSalePrice",
4664
+ args: [
4665
+ plan.nftAddress,
4666
+ plan.tokenId,
4667
+ plan.currency,
4668
+ plan.price,
4669
+ plan.target,
4670
+ plan.splitAddresses,
4671
+ plan.splitRatios
4672
+ ],
4673
+ account,
4674
+ chain: void 0
4675
+ });
4676
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
4677
+ return { txHash: targetTxHash, receipt: targetReceipt };
4678
+ }
4520
4679
  });
4521
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
4522
4680
  return { txHash, receipt, approvalTxHash };
4523
4681
  },
4524
4682
  async cancel(params) {
4525
4683
  const { walletClient, account } = requireWallet(config);
4526
4684
  const plan = planListingCancel(params);
4527
- const txHash = await walletClient.writeContract({
4685
+ const targetTxHash = await walletClient.writeContract({
4528
4686
  address: addresses.auction,
4529
4687
  abi: auctionAbi,
4530
4688
  functionName: "removeSalePrice",
@@ -4532,8 +4690,8 @@ function createListingNamespace(publicClient, config, chain, addresses) {
4532
4690
  account,
4533
4691
  chain: void 0
4534
4692
  });
4535
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
4536
- return { txHash, receipt };
4693
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
4694
+ return { txHash: targetTxHash, receipt: targetReceipt };
4537
4695
  },
4538
4696
  async buy(params) {
4539
4697
  const { walletClient, account, accountAddress } = requireWallet(config);
@@ -4552,16 +4710,28 @@ function createListingNamespace(publicClient, config, chain, addresses) {
4552
4710
  amount: plan.amount,
4553
4711
  autoApprove: params.autoApprove
4554
4712
  });
4555
- const txHash = await walletClient.writeContract({
4556
- address: addresses.auction,
4557
- abi: auctionAbi,
4558
- functionName: "buy",
4559
- args: [params.contract, plan.tokenId, plan.currency, plan.amount],
4560
- account,
4561
- chain: void 0,
4562
- value: payment.value
4713
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
4714
+ operation: "listing buy",
4715
+ approvals: [{
4716
+ type: "erc20",
4717
+ approvalTxHash: payment.approvalTxHash,
4718
+ target: plan.currency,
4719
+ spender: addresses.auction
4720
+ }],
4721
+ run: async () => {
4722
+ const targetTxHash = await walletClient.writeContract({
4723
+ address: addresses.auction,
4724
+ abi: auctionAbi,
4725
+ functionName: "buy",
4726
+ args: [params.contract, plan.tokenId, plan.currency, plan.amount],
4727
+ account,
4728
+ chain: void 0,
4729
+ value: payment.value
4730
+ });
4731
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
4732
+ return { txHash: targetTxHash, receipt: targetReceipt };
4733
+ }
4563
4734
  });
4564
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
4565
4735
  return { txHash, receipt, approvalTxHash: payment.approvalTxHash };
4566
4736
  },
4567
4737
  async status(params) {
@@ -5368,7 +5538,7 @@ function createBatchListingNamespace(publicClient, config, addresses) {
5368
5538
  );
5369
5539
  }
5370
5540
  }
5371
- const approvalTxHashes = await approveNftContracts({
5541
+ const nftApprovals = await approveNftContracts({
5372
5542
  publicClient,
5373
5543
  walletClient,
5374
5544
  account,
@@ -5377,26 +5547,38 @@ function createBatchListingNamespace(publicClient, config, addresses) {
5377
5547
  nftAddresses: uniqueContracts,
5378
5548
  autoApprove: params.autoApprove
5379
5549
  });
5380
- const txHash = await walletClient.writeContract({
5381
- address: addresses.batchListing,
5382
- abi: batchListingAbi,
5383
- functionName: "registerSalePriceMerkleRoot",
5384
- args: [
5385
- artifact.root,
5386
- artifact.currency,
5387
- BigInt(artifact.amount),
5388
- splitConfig.splitAddresses,
5389
- splitConfig.splitRatios
5390
- ],
5391
- account,
5392
- chain: void 0
5550
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
5551
+ operation: "batch listing create",
5552
+ approvals: nftApprovals.map((approval) => ({
5553
+ type: "nft",
5554
+ approvalTxHash: approval.txHash,
5555
+ target: approval.nftAddress,
5556
+ operator: addresses.erc721ApprovalManager
5557
+ })),
5558
+ run: async () => {
5559
+ const targetTxHash = await walletClient.writeContract({
5560
+ address: addresses.batchListing,
5561
+ abi: batchListingAbi,
5562
+ functionName: "registerSalePriceMerkleRoot",
5563
+ args: [
5564
+ artifact.root,
5565
+ artifact.currency,
5566
+ BigInt(artifact.amount),
5567
+ splitConfig.splitAddresses,
5568
+ splitConfig.splitRatios
5569
+ ],
5570
+ account,
5571
+ chain: void 0
5572
+ });
5573
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5574
+ return { txHash: targetTxHash, receipt: targetReceipt };
5575
+ }
5393
5576
  });
5394
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5395
5577
  return {
5396
5578
  txHash,
5397
5579
  receipt,
5398
5580
  root: artifact.root,
5399
- approvalTxHashes: approvalTxHashes.length > 0 ? approvalTxHashes : void 0
5581
+ approvalTxHashes: nftApprovals.length > 0 ? nftApprovals.map((approval) => approval.txHash) : void 0
5400
5582
  };
5401
5583
  },
5402
5584
  async cancel(params) {
@@ -5409,7 +5591,7 @@ function createBatchListingNamespace(publicClient, config, addresses) {
5409
5591
  creator: accountAddress,
5410
5592
  params
5411
5593
  });
5412
- const txHash = await walletClient.writeContract({
5594
+ const targetTxHash = await walletClient.writeContract({
5413
5595
  address: addresses.batchListing,
5414
5596
  abi: batchListingAbi,
5415
5597
  functionName: "cancelSalePriceMerkleRoot",
@@ -5417,8 +5599,8 @@ function createBatchListingNamespace(publicClient, config, addresses) {
5417
5599
  account,
5418
5600
  chain: void 0
5419
5601
  });
5420
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5421
- return { txHash, receipt, root };
5602
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5603
+ return { txHash: targetTxHash, receipt: targetReceipt, root };
5422
5604
  },
5423
5605
  async buy(params) {
5424
5606
  const { walletClient, account, accountAddress } = requireWallet(config);
@@ -5449,25 +5631,37 @@ function createBatchListingNamespace(publicClient, config, addresses) {
5449
5631
  amount,
5450
5632
  autoApprove: params.autoApprove
5451
5633
  });
5452
- const txHash = await walletClient.writeContract({
5453
- address: addresses.batchListing,
5454
- abi: batchListingAbi,
5455
- functionName: "buyWithMerkleProof",
5456
- args: [
5457
- proofArtifact.contract,
5458
- tokenIdBig,
5459
- currency,
5460
- amount,
5461
- params.creator,
5462
- proofArtifact.root,
5463
- proofArtifact.proof,
5464
- allowListProof
5465
- ],
5466
- account,
5467
- chain: void 0,
5468
- value: payment.value
5634
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
5635
+ operation: "batch listing buy",
5636
+ approvals: [{
5637
+ type: "erc20",
5638
+ approvalTxHash: payment.approvalTxHash,
5639
+ target: currency,
5640
+ spender: addresses.erc20ApprovalManager
5641
+ }],
5642
+ run: async () => {
5643
+ const targetTxHash = await walletClient.writeContract({
5644
+ address: addresses.batchListing,
5645
+ abi: batchListingAbi,
5646
+ functionName: "buyWithMerkleProof",
5647
+ args: [
5648
+ proofArtifact.contract,
5649
+ tokenIdBig,
5650
+ currency,
5651
+ amount,
5652
+ params.creator,
5653
+ proofArtifact.root,
5654
+ proofArtifact.proof,
5655
+ allowListProof
5656
+ ],
5657
+ account,
5658
+ chain: void 0,
5659
+ value: payment.value
5660
+ });
5661
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5662
+ return { txHash: targetTxHash, receipt: targetReceipt };
5663
+ }
5469
5664
  });
5470
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5471
5665
  return { txHash, receipt, approvalTxHash: payment.approvalTxHash };
5472
5666
  },
5473
5667
  async setAllowlist(params) {
@@ -5485,7 +5679,7 @@ function createBatchListingNamespace(publicClient, config, addresses) {
5485
5679
  requireInput(params.endTime ?? params.artifact?.allowList?.endTimestamp, "endTime"),
5486
5680
  "endTime"
5487
5681
  );
5488
- const txHash = await walletClient.writeContract({
5682
+ const targetTxHash = await walletClient.writeContract({
5489
5683
  address: addresses.batchListing,
5490
5684
  abi: batchListingAbi,
5491
5685
  functionName: "setAllowListConfig",
@@ -5493,8 +5687,8 @@ function createBatchListingNamespace(publicClient, config, addresses) {
5493
5687
  account,
5494
5688
  chain: void 0
5495
5689
  });
5496
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5497
- return { txHash, receipt, root, allowListRoot, endTime };
5690
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5691
+ return { txHash: targetTxHash, receipt: targetReceipt, root, allowListRoot, endTime };
5498
5692
  },
5499
5693
  async status(params) {
5500
5694
  const resolvedParams = await resolveBatchListingStatusParams({
@@ -5723,7 +5917,7 @@ function isHash(value) {
5723
5917
  }
5724
5918
  async function approveNftContracts(opts) {
5725
5919
  return opts.nftAddresses.reduce(async (previous, nftAddress) => {
5726
- const hashes = await previous;
5920
+ const approvals = await previous;
5727
5921
  const txHash = await approveNftContractIfNeeded({
5728
5922
  publicClient: opts.publicClient,
5729
5923
  walletClient: opts.walletClient,
@@ -5733,7 +5927,7 @@ async function approveNftContracts(opts) {
5733
5927
  operator: opts.operator,
5734
5928
  autoApprove: opts.autoApprove
5735
5929
  });
5736
- return isHash(txHash) ? [...hashes, txHash] : hashes;
5930
+ return isHash(txHash) ? [...approvals, { nftAddress, txHash }] : approvals;
5737
5931
  }, Promise.resolve([]));
5738
5932
  }
5739
5933
  async function prepareBatchListingPayment(opts) {
@@ -6104,16 +6298,18 @@ function planBatchAuctionStatus(params) {
6104
6298
  }
6105
6299
  function shapeBatchAuctionStatus(details, currentBid, rootContext, nowSeconds) {
6106
6300
  const hasAuction = details.startingTime > 0n && !isAddressEqual10(details.seller, zeroAddress3);
6107
- const hasRootConfig = rootContext !== void 0 && rootContext.config.duration > 0n;
6108
- const duration = hasAuction ? details.duration : rootContext?.config.duration ?? 0n;
6301
+ const hasCurrentRootConfig = rootContext !== void 0 && rootContext.config.duration > 0n && rootContext.rootNonce === rootContext.config.nonce;
6302
+ const currentRootConfig = hasCurrentRootConfig ? rootContext.config : void 0;
6303
+ const hasRootConfig = currentRootConfig !== void 0;
6304
+ const duration = hasAuction ? details.duration : currentRootConfig?.duration ?? 0n;
6109
6305
  const startingTime = hasAuction ? details.startingTime : 0n;
6110
6306
  const endTime = hasAuction ? startingTime + duration : null;
6111
6307
  const ended = endTime !== null && nowSeconds >= endTime;
6112
6308
  const currentBidder = currentBid.amount > 0n && !isAddressEqual10(currentBid.bidder, zeroAddress3) ? currentBid.bidder : null;
6113
6309
  const seller = hasAuction ? details.seller : rootContext?.creator ?? zeroAddress3;
6114
- const currency = hasAuction ? details.currency : rootContext?.config.currency ?? ETH_ADDRESS;
6115
- const reserveAmount = hasAuction ? details.reserveAmount : rootContext?.config.reserveAmount ?? 0n;
6116
- const tokenNonceConsumed = rootContext === void 0 ? null : rootContext.tokenNonce >= rootContext.config.nonce;
6310
+ const currency = hasAuction ? details.currency : currentRootConfig?.currency ?? ETH_ADDRESS;
6311
+ const reserveAmount = hasAuction ? details.reserveAmount : currentRootConfig?.reserveAmount ?? 0n;
6312
+ const tokenNonceConsumed = rootContext === void 0 ? null : !hasCurrentRootConfig || rootContext.tokenNonce >= rootContext.config.nonce;
6117
6313
  return {
6118
6314
  seller,
6119
6315
  root: rootContext?.root ?? null,
@@ -6123,8 +6319,8 @@ function shapeBatchAuctionStatus(details, currentBid, rootContext, nowSeconds) {
6123
6319
  creationBlock: details.creationBlock,
6124
6320
  startingTime,
6125
6321
  endTime,
6126
- splitAddresses: resolveStatusSplitAddresses(hasAuction, details, rootContext),
6127
- splitRatios: resolveStatusSplitRatios(hasAuction, details, rootContext),
6322
+ splitAddresses: resolveStatusSplitAddresses(hasAuction, details, currentRootConfig),
6323
+ splitRatios: resolveStatusSplitRatios(hasAuction, details, currentRootConfig),
6128
6324
  hasRootConfig,
6129
6325
  rootNonce: rootContext?.rootNonce ?? null,
6130
6326
  tokenNonce: rootContext?.tokenNonce ?? null,
@@ -6260,23 +6456,23 @@ function uniqueAddresses2(addresses) {
6260
6456
  function addMinimumBidIncrease(amount) {
6261
6457
  return amount + amount * marketplaceFeePercentage / 100n;
6262
6458
  }
6263
- function resolveStatusSplitAddresses(hasAuction, details, rootContext) {
6459
+ function resolveStatusSplitAddresses(hasAuction, details, rootConfig) {
6264
6460
  if (hasAuction) {
6265
6461
  return [...details.splitAddresses];
6266
6462
  }
6267
- if (rootContext === void 0) {
6463
+ if (rootConfig === void 0) {
6268
6464
  return [];
6269
6465
  }
6270
- return [...rootContext.config.splitAddresses];
6466
+ return [...rootConfig.splitAddresses];
6271
6467
  }
6272
- function resolveStatusSplitRatios(hasAuction, details, rootContext) {
6468
+ function resolveStatusSplitRatios(hasAuction, details, rootConfig) {
6273
6469
  if (hasAuction) {
6274
6470
  return [...details.splitRatios];
6275
6471
  }
6276
- if (rootContext === void 0) {
6472
+ if (rootConfig === void 0) {
6277
6473
  return [];
6278
6474
  }
6279
- return [...rootContext.config.splitRatios];
6475
+ return [...rootConfig.splitRatios];
6280
6476
  }
6281
6477
  function resolveBatchAuctionState(params) {
6282
6478
  if (params.hasAuction) {
@@ -6310,7 +6506,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
6310
6506
  currentUnixTimestamp2()
6311
6507
  );
6312
6508
  const erc721ApprovalManager = plan.approvalContracts.length === 0 ? void 0 : requireContractAddress(chain, "erc721ApprovalManager");
6313
- const approvalTxHashes = await approveNftContracts2({
6509
+ const nftApprovals = await approveNftContracts2({
6314
6510
  publicClient,
6315
6511
  account,
6316
6512
  accountAddress,
@@ -6319,31 +6515,43 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
6319
6515
  nftAddresses: plan.approvalContracts,
6320
6516
  autoApprove: params.autoApprove
6321
6517
  });
6322
- const txHash = await walletClient.writeContract({
6323
- address: batchAuctionHouse,
6324
- abi: batchAuctionHouseAbi,
6325
- functionName: "registerAuctionMerkleRoot",
6326
- args: [
6327
- plan.root,
6328
- plan.currency,
6329
- plan.reserveAmount,
6330
- plan.duration,
6331
- plan.splitAddresses,
6332
- plan.splitRatios
6333
- ],
6334
- account,
6335
- chain: void 0
6336
- });
6337
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
6338
- const logs = parseEventLogs3({
6339
- abi: batchAuctionHouseAbi,
6340
- logs: receipt.logs,
6341
- eventName: "AuctionMerkleRootRegistered"
6518
+ const { txHash, receipt, registered } = await runWithApprovalSideEffectAlert({
6519
+ operation: "batch auction create",
6520
+ approvals: nftApprovals.map((approval) => ({
6521
+ type: "nft",
6522
+ approvalTxHash: approval.txHash,
6523
+ target: approval.nftAddress,
6524
+ operator: erc721ApprovalManager
6525
+ })),
6526
+ run: async () => {
6527
+ const targetTxHash = await walletClient.writeContract({
6528
+ address: batchAuctionHouse,
6529
+ abi: batchAuctionHouseAbi,
6530
+ functionName: "registerAuctionMerkleRoot",
6531
+ args: [
6532
+ plan.root,
6533
+ plan.currency,
6534
+ plan.reserveAmount,
6535
+ plan.duration,
6536
+ plan.splitAddresses,
6537
+ plan.splitRatios
6538
+ ],
6539
+ account,
6540
+ chain: void 0
6541
+ });
6542
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
6543
+ const logs = parseEventLogs3({
6544
+ abi: batchAuctionHouseAbi,
6545
+ logs: targetReceipt.logs,
6546
+ eventName: "AuctionMerkleRootRegistered"
6547
+ });
6548
+ const [registeredLog] = logs;
6549
+ if (!registeredLog) {
6550
+ throw new Error("Batch auction create transaction succeeded but AuctionMerkleRootRegistered was not found in logs.");
6551
+ }
6552
+ return { txHash: targetTxHash, receipt: targetReceipt, registered: registeredLog };
6553
+ }
6342
6554
  });
6343
- const [registered] = logs;
6344
- if (!registered) {
6345
- throw new Error("Batch auction create transaction succeeded but AuctionMerkleRootRegistered was not found in logs.");
6346
- }
6347
6555
  return {
6348
6556
  txHash,
6349
6557
  receipt,
@@ -6354,7 +6562,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
6354
6562
  reserveAmount: registered.args.startingAmount,
6355
6563
  duration: registered.args.duration,
6356
6564
  nonce: registered.args.nonce,
6357
- approvalTxHashes
6565
+ approvalTxHashes: nftApprovals.map((approval) => approval.txHash)
6358
6566
  };
6359
6567
  },
6360
6568
  async cancel(params) {
@@ -6367,7 +6575,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
6367
6575
  params
6368
6576
  );
6369
6577
  const plan = planBatchAuctionRoot(resolvedParams);
6370
- const txHash = await walletClient.writeContract({
6578
+ const targetTxHash = await walletClient.writeContract({
6371
6579
  address: batchAuctionHouse,
6372
6580
  abi: batchAuctionHouseAbi,
6373
6581
  functionName: "cancelAuctionMerkleRoot",
@@ -6375,10 +6583,10 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
6375
6583
  account,
6376
6584
  chain: void 0
6377
6585
  });
6378
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
6586
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
6379
6587
  const logs = parseEventLogs3({
6380
6588
  abi: batchAuctionHouseAbi,
6381
- logs: receipt.logs,
6589
+ logs: targetReceipt.logs,
6382
6590
  eventName: "AuctionMerkleRootCancelled"
6383
6591
  });
6384
6592
  const [cancelled] = logs;
@@ -6386,8 +6594,8 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
6386
6594
  throw new Error("Batch auction cancel transaction succeeded but AuctionMerkleRootCancelled was not found in logs.");
6387
6595
  }
6388
6596
  return {
6389
- txHash,
6390
- receipt,
6597
+ txHash: targetTxHash,
6598
+ receipt: targetReceipt,
6391
6599
  batchAuctionHouse,
6392
6600
  creator: cancelled.args.creator,
6393
6601
  root: cancelled.args.merkleRoot
@@ -6428,33 +6636,45 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
6428
6636
  requiredAmount: plan.requiredPayment,
6429
6637
  autoApprove: params.autoApprove
6430
6638
  });
6431
- const txHash = await walletClient.writeContract({
6432
- address: batchAuctionHouse,
6433
- abi: batchAuctionHouseAbi,
6434
- functionName: "bidWithAuctionMerkleProof",
6435
- args: [
6436
- plan.currency,
6437
- plan.contract,
6438
- plan.tokenId,
6439
- plan.creator,
6440
- plan.root,
6441
- plan.amount,
6442
- plan.proof
6443
- ],
6444
- account,
6445
- chain: void 0,
6446
- value: payment.value
6447
- });
6448
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
6449
- const logs = parseEventLogs3({
6450
- abi: batchAuctionHouseAbi,
6451
- logs: receipt.logs,
6452
- eventName: "AuctionMerkleBid"
6639
+ const { txHash, receipt, bid } = await runWithApprovalSideEffectAlert({
6640
+ operation: "batch auction bid",
6641
+ approvals: [{
6642
+ type: "erc20",
6643
+ approvalTxHash: payment.approvalTxHash,
6644
+ target: plan.currency,
6645
+ spender: erc20ApprovalManager
6646
+ }],
6647
+ run: async () => {
6648
+ const targetTxHash = await walletClient.writeContract({
6649
+ address: batchAuctionHouse,
6650
+ abi: batchAuctionHouseAbi,
6651
+ functionName: "bidWithAuctionMerkleProof",
6652
+ args: [
6653
+ plan.currency,
6654
+ plan.contract,
6655
+ plan.tokenId,
6656
+ plan.creator,
6657
+ plan.root,
6658
+ plan.amount,
6659
+ plan.proof
6660
+ ],
6661
+ account,
6662
+ chain: void 0,
6663
+ value: payment.value
6664
+ });
6665
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
6666
+ const logs = parseEventLogs3({
6667
+ abi: batchAuctionHouseAbi,
6668
+ logs: targetReceipt.logs,
6669
+ eventName: "AuctionMerkleBid"
6670
+ });
6671
+ const [bidLog] = logs;
6672
+ if (!bidLog) {
6673
+ throw new Error("Batch auction bid transaction succeeded but AuctionMerkleBid was not found in logs.");
6674
+ }
6675
+ return { txHash: targetTxHash, receipt: targetReceipt, bid: bidLog };
6676
+ }
6453
6677
  });
6454
- const [bid] = logs;
6455
- if (!bid) {
6456
- throw new Error("Batch auction bid transaction succeeded but AuctionMerkleBid was not found in logs.");
6457
- }
6458
6678
  return {
6459
6679
  txHash,
6460
6680
  receipt,
@@ -6475,7 +6695,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
6475
6695
  const batchAuctionHouse = requireContractAddress(chain, "batchAuctionHouse");
6476
6696
  const { walletClient, account } = requireWallet(config);
6477
6697
  const plan = planBatchAuctionStatus(params);
6478
- const txHash = await walletClient.writeContract({
6698
+ const targetTxHash = await walletClient.writeContract({
6479
6699
  address: batchAuctionHouse,
6480
6700
  abi: batchAuctionHouseAbi,
6481
6701
  functionName: "settleAuction",
@@ -6483,10 +6703,10 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
6483
6703
  account,
6484
6704
  chain: void 0
6485
6705
  });
6486
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
6706
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
6487
6707
  const logs = parseEventLogs3({
6488
6708
  abi: batchAuctionHouseAbi,
6489
- logs: receipt.logs,
6709
+ logs: targetReceipt.logs,
6490
6710
  eventName: "AuctionSettled"
6491
6711
  });
6492
6712
  const [settled] = logs;
@@ -6494,8 +6714,8 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
6494
6714
  throw new Error("Batch auction settle transaction succeeded but AuctionSettled was not found in logs.");
6495
6715
  }
6496
6716
  return {
6497
- txHash,
6498
- receipt,
6717
+ txHash: targetTxHash,
6718
+ receipt: targetReceipt,
6499
6719
  batchAuctionHouse,
6500
6720
  seller: settled.args.seller,
6501
6721
  bidder: settled.args.bidder,
@@ -6682,7 +6902,7 @@ async function approveNftContracts2(opts) {
6682
6902
  }
6683
6903
  const { walletClient, operator } = opts;
6684
6904
  return opts.nftAddresses.reduce(async (previous, nftAddress) => {
6685
- const hashes = await previous;
6905
+ const approvals = await previous;
6686
6906
  const txHash = await approveNftContract({
6687
6907
  publicClient: opts.publicClient,
6688
6908
  walletClient,
@@ -6692,7 +6912,7 @@ async function approveNftContracts2(opts) {
6692
6912
  nftAddress,
6693
6913
  autoApprove: opts.autoApprove
6694
6914
  });
6695
- return txHash === void 0 ? hashes : [...hashes, txHash];
6915
+ return txHash === void 0 ? approvals : [...approvals, { nftAddress, txHash }];
6696
6916
  }, Promise.resolve([]));
6697
6917
  }
6698
6918
  async function approveNftContract(opts) {
@@ -7032,25 +7252,37 @@ function createBatchOfferNamespace(publicClient, config, chain) {
7032
7252
  amount: plan.amount,
7033
7253
  autoApprove: params.autoApprove
7034
7254
  });
7035
- const txHash = await walletClient.writeContract({
7036
- address: batchOfferCreator,
7037
- abi: batchOfferAbi,
7038
- functionName: "createBatchOffer",
7039
- args: [plan.root, plan.amount, plan.currency, plan.expiry],
7040
- account,
7041
- chain: void 0,
7042
- value: payment.value
7043
- });
7044
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
7045
- const logs = parseEventLogs4({
7046
- abi: batchOfferAbi,
7047
- logs: receipt.logs,
7048
- eventName: "BatchOfferCreated"
7255
+ const { txHash, receipt, created } = await runWithApprovalSideEffectAlert({
7256
+ operation: "batch offer create",
7257
+ approvals: [{
7258
+ type: "erc20",
7259
+ approvalTxHash: payment.approvalTxHash,
7260
+ target: plan.currency,
7261
+ spender: batchOfferCreator
7262
+ }],
7263
+ run: async () => {
7264
+ const targetTxHash = await walletClient.writeContract({
7265
+ address: batchOfferCreator,
7266
+ abi: batchOfferAbi,
7267
+ functionName: "createBatchOffer",
7268
+ args: [plan.root, plan.amount, plan.currency, plan.expiry],
7269
+ account,
7270
+ chain: void 0,
7271
+ value: payment.value
7272
+ });
7273
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
7274
+ const logs = parseEventLogs4({
7275
+ abi: batchOfferAbi,
7276
+ logs: targetReceipt.logs,
7277
+ eventName: "BatchOfferCreated"
7278
+ });
7279
+ const [createdLog] = logs;
7280
+ if (!createdLog) {
7281
+ throw new Error("Batch offer create transaction succeeded but BatchOfferCreated was not found in logs.");
7282
+ }
7283
+ return { txHash: targetTxHash, receipt: targetReceipt, created: createdLog };
7284
+ }
7049
7285
  });
7050
- const [created] = logs;
7051
- if (!created) {
7052
- throw new Error("Batch offer create transaction succeeded but BatchOfferCreated was not found in logs.");
7053
- }
7054
7286
  return {
7055
7287
  txHash,
7056
7288
  receipt,
@@ -7076,7 +7308,7 @@ function createBatchOfferNamespace(publicClient, config, chain) {
7076
7308
  params
7077
7309
  });
7078
7310
  const plan = planBatchOfferRoot(resolvedParams);
7079
- const txHash = await walletClient.writeContract({
7311
+ const targetTxHash = await walletClient.writeContract({
7080
7312
  address: batchOfferCreator,
7081
7313
  abi: batchOfferAbi,
7082
7314
  functionName: "revokeBatchOffer",
@@ -7084,10 +7316,10 @@ function createBatchOfferNamespace(publicClient, config, chain) {
7084
7316
  account,
7085
7317
  chain: void 0
7086
7318
  });
7087
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
7319
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
7088
7320
  const logs = parseEventLogs4({
7089
7321
  abi: batchOfferAbi,
7090
- logs: receipt.logs,
7322
+ logs: targetReceipt.logs,
7091
7323
  eventName: "BatchOfferRevoked"
7092
7324
  });
7093
7325
  const [revoked] = logs;
@@ -7095,8 +7327,8 @@ function createBatchOfferNamespace(publicClient, config, chain) {
7095
7327
  throw new Error("Batch offer revoke transaction succeeded but BatchOfferRevoked was not found in logs.");
7096
7328
  }
7097
7329
  return {
7098
- txHash,
7099
- receipt,
7330
+ txHash: targetTxHash,
7331
+ receipt: targetReceipt,
7100
7332
  batchOfferCreator,
7101
7333
  creator: revoked.args.creator,
7102
7334
  root: revoked.args.rootHash,
@@ -7133,32 +7365,44 @@ function createBatchOfferNamespace(publicClient, config, chain) {
7133
7365
  operator: batchOfferCreator,
7134
7366
  autoApprove: plan.autoApprove
7135
7367
  });
7136
- const txHash = await walletClient.writeContract({
7137
- address: batchOfferCreator,
7138
- abi: batchOfferAbi,
7139
- functionName: "acceptBatchOffer",
7140
- args: [
7141
- plan.creator,
7142
- plan.proof,
7143
- plan.root,
7144
- plan.contract,
7145
- plan.tokenId,
7146
- plan.splitAddresses,
7147
- plan.splitRatios
7148
- ],
7149
- account,
7150
- chain: void 0
7151
- });
7152
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
7153
- const logs = parseEventLogs4({
7154
- abi: batchOfferAbi,
7155
- logs: receipt.logs,
7156
- eventName: "BatchOfferAccepted"
7368
+ const { txHash, receipt, accepted } = await runWithApprovalSideEffectAlert({
7369
+ operation: "batch offer accept",
7370
+ approvals: [{
7371
+ type: "nft",
7372
+ approvalTxHash,
7373
+ target: plan.contract,
7374
+ operator: batchOfferCreator
7375
+ }],
7376
+ run: async () => {
7377
+ const targetTxHash = await walletClient.writeContract({
7378
+ address: batchOfferCreator,
7379
+ abi: batchOfferAbi,
7380
+ functionName: "acceptBatchOffer",
7381
+ args: [
7382
+ plan.creator,
7383
+ plan.proof,
7384
+ plan.root,
7385
+ plan.contract,
7386
+ plan.tokenId,
7387
+ plan.splitAddresses,
7388
+ plan.splitRatios
7389
+ ],
7390
+ account,
7391
+ chain: void 0
7392
+ });
7393
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
7394
+ const logs = parseEventLogs4({
7395
+ abi: batchOfferAbi,
7396
+ logs: targetReceipt.logs,
7397
+ eventName: "BatchOfferAccepted"
7398
+ });
7399
+ const [acceptedLog] = logs;
7400
+ if (!acceptedLog) {
7401
+ throw new Error("Batch offer accept transaction succeeded but BatchOfferAccepted was not found in logs.");
7402
+ }
7403
+ return { txHash: targetTxHash, receipt: targetReceipt, accepted: acceptedLog };
7404
+ }
7157
7405
  });
7158
- const [accepted] = logs;
7159
- if (!accepted) {
7160
- throw new Error("Batch offer accept transaction succeeded but BatchOfferAccepted was not found in logs.");
7161
- }
7162
7406
  return {
7163
7407
  txHash,
7164
7408
  receipt,
@@ -7779,6 +8023,7 @@ var liquidFactoryAbi = [
7779
8023
  var TICK_BASE = 1.0001;
7780
8024
  var TICK_LOG_BASE = Math.log(TICK_BASE);
7781
8025
  var TOKEN_BASE_UNITS = 1e18;
8026
+ var SHARE_SCALE_UNITS = 10n ** 18n;
7782
8027
  var RESERVE_TAIL_SHARES_PERCENT = 2;
7783
8028
  var RESERVE_TAIL_END_PRICE_MULTIPLE = 100;
7784
8029
  var SHARES_SUM_TOLERANCE = 1e-6;
@@ -7837,12 +8082,66 @@ function toValidNumber(value) {
7837
8082
  if (typeof value !== "number" || !Number.isFinite(value)) return null;
7838
8083
  return value;
7839
8084
  }
7840
- function toValidShareNumber(value) {
7841
- const numeric = typeof value === "string" ? Number(value) : toValidNumber(value);
7842
- if (numeric === null || numeric <= 0 || numeric > 1) {
8085
+ function toNormalizedShare(value) {
8086
+ if (typeof value === "number") {
8087
+ if (!Number.isFinite(value) || value <= 0 || value > 1) {
8088
+ return null;
8089
+ }
8090
+ return parseShareDecimalString(expandFiniteNumber(value));
8091
+ }
8092
+ if (typeof value !== "string") {
7843
8093
  return null;
7844
8094
  }
7845
- return numeric;
8095
+ return parseShareDecimalString(value);
8096
+ }
8097
+ function expandFiniteNumber(value) {
8098
+ const rawValue = value.toString();
8099
+ const [coefficient = "", exponentValue] = rawValue.toLowerCase().split("e");
8100
+ if (exponentValue === void 0) {
8101
+ return rawValue;
8102
+ }
8103
+ const exponent = Number(exponentValue);
8104
+ const [integerPart = "", fractionalPart = ""] = coefficient.split(".");
8105
+ const digits = `${integerPart}${fractionalPart}`;
8106
+ const decimalIndex = integerPart.length + exponent;
8107
+ if (decimalIndex <= 0) {
8108
+ return `0.${"0".repeat(Math.abs(decimalIndex))}${digits}`;
8109
+ }
8110
+ if (decimalIndex >= digits.length) {
8111
+ return `${digits}${"0".repeat(decimalIndex - digits.length)}`;
8112
+ }
8113
+ return `${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`;
8114
+ }
8115
+ function parseShareDecimalString(value) {
8116
+ const normalized = value.trim();
8117
+ if (!/^(?:\d+\.?\d*|\.\d+)$/.test(normalized)) {
8118
+ return null;
8119
+ }
8120
+ const shareParts = normalized.startsWith(".") ? ["0", normalized.slice(1)] : normalized.split(".");
8121
+ const integerPart = shareParts[0] ?? "";
8122
+ const fractionalDigits = shareParts[1] ?? "";
8123
+ const excessFractionalDigits = fractionalDigits.slice(18);
8124
+ if (/[1-9]/.test(excessFractionalDigits)) {
8125
+ return null;
8126
+ }
8127
+ const integerUnits = BigInt(integerPart === "" ? "0" : integerPart);
8128
+ const fractionalUnits = BigInt(fractionalDigits.slice(0, 18).padEnd(18, "0"));
8129
+ const scaledUnits = integerUnits * SHARE_SCALE_UNITS + fractionalUnits;
8130
+ if (scaledUnits <= 0n || scaledUnits > SHARE_SCALE_UNITS) {
8131
+ return null;
8132
+ }
8133
+ return {
8134
+ decimal: formatScaledShareDecimal(scaledUnits),
8135
+ scaledUnits
8136
+ };
8137
+ }
8138
+ function formatScaledShareDecimal(scaledUnits) {
8139
+ const integerUnits = scaledUnits / SHARE_SCALE_UNITS;
8140
+ const fractionalUnits = scaledUnits % SHARE_SCALE_UNITS;
8141
+ if (fractionalUnits === 0n) {
8142
+ return integerUnits.toString();
8143
+ }
8144
+ return `${integerUnits}.${fractionalUnits.toString().padStart(18, "0").replace(/0+$/, "")}`;
7846
8145
  }
7847
8146
  function toApproxTokenAmount(value, label) {
7848
8147
  const numeric = typeof value === "number" ? value : Number(value);
@@ -7991,8 +8290,8 @@ function validateAndNormalizeSegments(rawSegments, totalCurveSupplyTokens, tickS
7991
8290
  if (invalidResult !== void 0) {
7992
8291
  return invalidResult.result;
7993
8292
  }
7994
- const parsedSegments = normalizedResults.filter((result) => result.isValid).map((result) => result.segment);
7995
- const totalPositions = parsedSegments.reduce((sum, segment) => sum + segment.numPositions, 0);
8293
+ const parsedEntries = normalizedResults.filter((result) => result.isValid).map((result) => result.entry);
8294
+ const totalPositions = parsedEntries.reduce((sum, entry) => sum + entry.segment.numPositions, 0);
7996
8295
  if (totalPositions > MAX_TOTAL_POSITIONS) {
7997
8296
  return {
7998
8297
  isValid: false,
@@ -8000,8 +8299,8 @@ function validateAndNormalizeSegments(rawSegments, totalCurveSupplyTokens, tickS
8000
8299
  errorMessage: `Total positions across all curves must not exceed ${MAX_TOTAL_POSITIONS}`
8001
8300
  };
8002
8301
  }
8003
- const sortedSegments = [...parsedSegments].sort((a, b) => a.tickLower - b.tickLower);
8004
- const hasGapOrOverlap = sortedSegments.slice(1).some((current, index) => current.tickLower !== sortedSegments[index]?.tickUpper);
8302
+ const sortedEntries = [...parsedEntries].sort((a, b) => a.segment.tickLower - b.segment.tickLower);
8303
+ const hasGapOrOverlap = sortedEntries.slice(1).some((current, index) => current.segment.tickLower !== sortedEntries[index]?.segment.tickUpper);
8005
8304
  if (hasGapOrOverlap) {
8006
8305
  return {
8007
8306
  isValid: false,
@@ -8009,10 +8308,11 @@ function validateAndNormalizeSegments(rawSegments, totalCurveSupplyTokens, tickS
8009
8308
  errorMessage: "Curve segments must be contiguous (no overlap or gaps)"
8010
8309
  };
8011
8310
  }
8012
- const shareSum = sortedSegments.reduce((sum, segment) => sum + Number(segment.shares), 0);
8013
- if (Math.abs(shareSum - 1) > SHARES_SUM_TOLERANCE) {
8311
+ const shareSum = sortedEntries.reduce((sum, entry) => sum + entry.shareScaledUnits, 0n);
8312
+ if (shareSum !== SHARE_SCALE_UNITS) {
8014
8313
  return { isValid: false, error: "share-sum-invalid", errorMessage: "Curve share values must add up to 1" };
8015
8314
  }
8315
+ const sortedSegments = sortedEntries.map((entry) => entry.segment);
8016
8316
  const narrowSegment = sortedSegments.find((segment) => {
8017
8317
  const minSpan = segment.numPositions * tickSpacing;
8018
8318
  return segment.tickUpper - segment.tickLower < minSpan || computeGrossLiquidityAtFarTick(segment.tickLower, segment.tickUpper - segment.tickLower, segment.numPositions, Number(segment.shares), totalCurveSupplyTokens) > MAX_LIQUIDITY_PER_TICK;
@@ -8041,8 +8341,8 @@ function normalizeSegment(segment, tickSpacing) {
8041
8341
  const tickLower = toValidNumber(segment.tickLower);
8042
8342
  const tickUpper = toValidNumber(segment.tickUpper);
8043
8343
  const numPositions = toValidNumber(segment.numPositions);
8044
- const shares = toValidShareNumber(segment.shares);
8045
- if (tickLower === null || tickUpper === null || numPositions === null || shares === null) {
8344
+ const share = toNormalizedShare(segment.shares);
8345
+ if (tickLower === null || tickUpper === null || numPositions === null || share === null) {
8046
8346
  return invalidSegmentResult();
8047
8347
  }
8048
8348
  if (!Number.isInteger(tickLower) || !Number.isInteger(tickUpper) || !Number.isInteger(numPositions) || numPositions <= 0) {
@@ -8059,11 +8359,14 @@ function normalizeSegment(segment, tickSpacing) {
8059
8359
  }
8060
8360
  return {
8061
8361
  isValid: true,
8062
- segment: {
8063
- tickLower,
8064
- tickUpper,
8065
- numPositions,
8066
- shares: `${shares}`
8362
+ entry: {
8363
+ segment: {
8364
+ tickLower,
8365
+ tickUpper,
8366
+ numPositions,
8367
+ shares: share.decimal
8368
+ },
8369
+ shareScaledUnits: share.scaledUnits
8067
8370
  }
8068
8371
  };
8069
8372
  }
@@ -8430,9 +8733,23 @@ function missingLiquidEditionAddressError(txHash, receipt, cause) {
8430
8733
  const message = `Liquid Edition deploy transaction succeeded, but the deployed contract address could not be read from the LiquidTokenCreated event logs after ${LIQUID_EDITION_ADDRESS_LOG_RETRY_ATTEMPTS + 1} attempts. Transaction hash: ${txHash}. Block: ${receipt.blockNumber}. The connected RPC may be delayed or returning incomplete receipt logs; retry with a synced RPC or inspect the transaction hash.`;
8431
8734
  return cause instanceof Error ? new Error(message, { cause }) : new Error(message);
8432
8735
  }
8433
- function liquidEditionDeployRevertedError(txHash, receipt) {
8736
+ function liquidEditionRevertedReceiptError(message, txHash, receipt) {
8434
8737
  return new Error(
8435
- `Liquid Edition deploy transaction reverted before emitting LiquidTokenCreated. Transaction hash: ${txHash}. Block: ${receipt.blockNumber}.`
8738
+ `${message} Transaction hash: ${txHash}. Block: ${receipt.blockNumber}.`
8739
+ );
8740
+ }
8741
+ function liquidEditionDeployRevertedError(txHash, receipt) {
8742
+ return liquidEditionRevertedReceiptError(
8743
+ "Liquid Edition deploy transaction reverted before emitting LiquidTokenCreated.",
8744
+ txHash,
8745
+ receipt
8746
+ );
8747
+ }
8748
+ function liquidEditionSetRenderContractRevertedError(txHash, receipt) {
8749
+ return liquidEditionRevertedReceiptError(
8750
+ 'Liquid Edition setRenderContract transaction was confirmed with status "reverted".',
8751
+ txHash,
8752
+ receipt
8436
8753
  );
8437
8754
  }
8438
8755
  async function waitForLiquidEditionAddress(publicClient, txHash) {
@@ -8518,7 +8835,13 @@ function createLiquidNamespace(config, chain, addresses) {
8518
8835
  throw new Error(validation.errorMessage ?? "Invalid curve configuration");
8519
8836
  }
8520
8837
  const initialRareLiquidity = params.initialRareLiquidity !== void 0 ? await toTokenAmount(publicClient, factoryConfig.baseToken, params.initialRareLiquidity, "initialRareLiquidity") : 0n;
8521
- await ensureTokenAllowance(
8838
+ const curves = validation.curves.map((curve) => ({
8839
+ tickLower: curve.tickLower,
8840
+ tickUpper: curve.tickUpper,
8841
+ numPositions: curve.numPositions,
8842
+ shares: parseUnits6(curve.shares, 18)
8843
+ }));
8844
+ const approvalTxHash = await ensureTokenAllowance(
8522
8845
  publicClient,
8523
8846
  walletClient,
8524
8847
  account,
@@ -8527,43 +8850,49 @@ function createLiquidNamespace(config, chain, addresses) {
8527
8850
  liquidFactory,
8528
8851
  initialRareLiquidity
8529
8852
  );
8530
- const curves = validation.curves.map((curve) => ({
8531
- tickLower: curve.tickLower,
8532
- tickUpper: curve.tickUpper,
8533
- numPositions: curve.numPositions,
8534
- shares: parseUnits6(curve.shares, 18)
8535
- }));
8536
- const txHash = customMaxTotalSupply === void 0 ? await walletClient.writeContract({
8537
- address: liquidFactory,
8538
- abi: liquidFactoryAbi,
8539
- functionName: "createLiquidTokenMultiCurve",
8540
- args: [
8541
- accountAddress,
8542
- params.tokenUri,
8543
- params.name,
8544
- params.symbol,
8545
- initialRareLiquidity,
8546
- curves
8547
- ],
8548
- account,
8549
- chain: void 0
8550
- }) : await walletClient.writeContract({
8551
- address: liquidFactory,
8552
- abi: liquidFactoryAbi,
8553
- functionName: "createLiquidTokenMultiCurveWithSupply",
8554
- args: [
8555
- accountAddress,
8556
- params.tokenUri,
8557
- params.name,
8558
- params.symbol,
8559
- initialRareLiquidity,
8560
- curves,
8561
- customMaxTotalSupply
8562
- ],
8563
- account,
8564
- chain: void 0
8853
+ const { txHash, receipt, contract } = await runWithApprovalSideEffectAlert({
8854
+ operation: "liquid edition deploy",
8855
+ approvals: [{
8856
+ type: "erc20",
8857
+ approvalTxHash,
8858
+ target: factoryConfig.baseToken,
8859
+ spender: liquidFactory
8860
+ }],
8861
+ run: async () => {
8862
+ const targetTxHash = customMaxTotalSupply === void 0 ? await walletClient.writeContract({
8863
+ address: liquidFactory,
8864
+ abi: liquidFactoryAbi,
8865
+ functionName: "createLiquidTokenMultiCurve",
8866
+ args: [
8867
+ accountAddress,
8868
+ params.tokenUri,
8869
+ params.name,
8870
+ params.symbol,
8871
+ initialRareLiquidity,
8872
+ curves
8873
+ ],
8874
+ account,
8875
+ chain: void 0
8876
+ }) : await walletClient.writeContract({
8877
+ address: liquidFactory,
8878
+ abi: liquidFactoryAbi,
8879
+ functionName: "createLiquidTokenMultiCurveWithSupply",
8880
+ args: [
8881
+ accountAddress,
8882
+ params.tokenUri,
8883
+ params.name,
8884
+ params.symbol,
8885
+ initialRareLiquidity,
8886
+ curves,
8887
+ customMaxTotalSupply
8888
+ ],
8889
+ account,
8890
+ chain: void 0
8891
+ });
8892
+ const deployed = await waitForLiquidEditionAddress(publicClient, targetTxHash);
8893
+ return { txHash: targetTxHash, receipt: deployed.receipt, contract: deployed.contract };
8894
+ }
8565
8895
  });
8566
- const { receipt, contract } = await waitForLiquidEditionAddress(publicClient, txHash);
8567
8896
  return {
8568
8897
  txHash,
8569
8898
  receipt,
@@ -8598,6 +8927,9 @@ function createLiquidNamespace(config, chain, addresses) {
8598
8927
  chain: void 0
8599
8928
  });
8600
8929
  const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
8930
+ if (receipt.status === "reverted") {
8931
+ throw liquidEditionSetRenderContractRevertedError(txHash, receipt);
8932
+ }
8601
8933
  return {
8602
8934
  txHash,
8603
8935
  receipt,
@@ -8704,6 +9036,312 @@ function createLiquidNamespace(config, chain, addresses) {
8704
9036
  };
8705
9037
  }
8706
9038
 
9039
+ // src/sdk/bridge.ts
9040
+ import { encodeFunctionData } from "viem";
9041
+
9042
+ // src/contracts/abis/rare-bridge.ts
9043
+ var rareBridgeAbi = [
9044
+ {
9045
+ type: "function",
9046
+ name: "getFee",
9047
+ inputs: [
9048
+ {
9049
+ name: "_destinationChainSelector",
9050
+ type: "uint64",
9051
+ internalType: "uint64"
9052
+ },
9053
+ {
9054
+ name: "_destinationChainRecipient",
9055
+ type: "address",
9056
+ internalType: "address"
9057
+ },
9058
+ {
9059
+ name: "_distributionData",
9060
+ type: "bytes",
9061
+ internalType: "bytes"
9062
+ },
9063
+ {
9064
+ name: "_extraArgs",
9065
+ type: "bytes",
9066
+ internalType: "bytes"
9067
+ },
9068
+ {
9069
+ name: "_payFeesInLink",
9070
+ type: "bool",
9071
+ internalType: "bool"
9072
+ }
9073
+ ],
9074
+ outputs: [
9075
+ {
9076
+ name: "fee",
9077
+ type: "uint256",
9078
+ internalType: "uint256"
9079
+ }
9080
+ ],
9081
+ stateMutability: "view"
9082
+ },
9083
+ {
9084
+ type: "function",
9085
+ name: "send",
9086
+ inputs: [
9087
+ {
9088
+ name: "_destinationChainSelector",
9089
+ type: "uint64",
9090
+ internalType: "uint64"
9091
+ },
9092
+ {
9093
+ name: "_destinationChainRecipient",
9094
+ type: "address",
9095
+ internalType: "address"
9096
+ },
9097
+ {
9098
+ name: "_distributionData",
9099
+ type: "bytes",
9100
+ internalType: "bytes"
9101
+ },
9102
+ {
9103
+ name: "_extraArgs",
9104
+ type: "bytes",
9105
+ internalType: "bytes"
9106
+ },
9107
+ {
9108
+ name: "_payFeesInLink",
9109
+ type: "bool",
9110
+ internalType: "bool"
9111
+ }
9112
+ ],
9113
+ outputs: [],
9114
+ stateMutability: "payable"
9115
+ },
9116
+ {
9117
+ type: "event",
9118
+ name: "MessageSent",
9119
+ inputs: [
9120
+ {
9121
+ name: "messageId",
9122
+ type: "bytes32",
9123
+ indexed: true,
9124
+ internalType: "bytes32"
9125
+ },
9126
+ {
9127
+ name: "destinationChainSelector",
9128
+ type: "uint64",
9129
+ indexed: true,
9130
+ internalType: "uint64"
9131
+ },
9132
+ {
9133
+ name: "destinationChainRecipient",
9134
+ type: "address",
9135
+ indexed: true,
9136
+ internalType: "address"
9137
+ },
9138
+ {
9139
+ name: "fee",
9140
+ type: "uint256",
9141
+ indexed: false,
9142
+ internalType: "uint256"
9143
+ },
9144
+ {
9145
+ name: "payFeesInLink",
9146
+ type: "bool",
9147
+ indexed: false,
9148
+ internalType: "bool"
9149
+ }
9150
+ ],
9151
+ anonymous: false
9152
+ }
9153
+ ];
9154
+
9155
+ // src/sdk/bridge-core.ts
9156
+ import { encodeAbiParameters } from "viem";
9157
+ var allowedBridgePairs = [
9158
+ { sourceChain: "mainnet", destinationChain: "base" },
9159
+ { sourceChain: "base", destinationChain: "mainnet" },
9160
+ { sourceChain: "sepolia", destinationChain: "base-sepolia" },
9161
+ { sourceChain: "base-sepolia", destinationChain: "sepolia" }
9162
+ ];
9163
+ function validateBridgeRoute(route) {
9164
+ const supported = allowedBridgePairs.some(
9165
+ (pair) => pair.sourceChain === route.sourceChain && pair.destinationChain === route.destinationChain
9166
+ );
9167
+ if (supported) {
9168
+ return { isValid: true };
9169
+ }
9170
+ return {
9171
+ isValid: false,
9172
+ error: "unsupported_bridge_route",
9173
+ errorMessage: `Unsupported RARE bridge route "${route.sourceChain}" -> "${route.destinationChain}". Supported routes: mainnet <-> base, sepolia <-> base-sepolia.`
9174
+ };
9175
+ }
9176
+ function getBridgeInfo(chain) {
9177
+ return {
9178
+ chain,
9179
+ chainId: chainIds[chain],
9180
+ rareBridgeAddress: getRareBridgeAddress(chain),
9181
+ rareTokenAddress: resolveCurrency("rare", chain),
9182
+ ccipChainSelector: getCcipChainSelector(chain)
9183
+ };
9184
+ }
9185
+ function encodeBridgeDistribution(params) {
9186
+ return encodeAbiParameters(
9187
+ [
9188
+ { name: "recipients", type: "address[]" },
9189
+ { name: "amounts", type: "uint256[]" }
9190
+ ],
9191
+ [[params.recipient], [params.amount]]
9192
+ );
9193
+ }
9194
+ function buildBridgeSendArgs(params) {
9195
+ return [
9196
+ params.destinationBridgeInfo.ccipChainSelector,
9197
+ params.destinationBridgeInfo.rareBridgeAddress,
9198
+ params.distributionData,
9199
+ "0x",
9200
+ false
9201
+ ];
9202
+ }
9203
+ function buildCcipExplorerUrl(txHash) {
9204
+ return `https://ccip.chain.link/tx/${txHash}`;
9205
+ }
9206
+
9207
+ // src/sdk/bridge.ts
9208
+ function createBridgeNamespace(publicClient, config, sourceChain) {
9209
+ return {
9210
+ async quote(params) {
9211
+ return buildBridgeQuote(publicClient, config, sourceChain, params);
9212
+ },
9213
+ async send(params) {
9214
+ return executeBridge(publicClient, config, sourceChain, params);
9215
+ }
9216
+ };
9217
+ }
9218
+ async function executeBridge(publicClient, config, sourceChain, params) {
9219
+ const { walletClient, account, accountAddress } = requireWallet(config);
9220
+ const quote = await buildBridgeQuote(publicClient, config, sourceChain, {
9221
+ ...params,
9222
+ recipient: params.recipient ?? accountAddress
9223
+ }, {
9224
+ estimateGas: false
9225
+ });
9226
+ const approval = await preparePaymentAmountForSpender({
9227
+ publicClient,
9228
+ walletClient,
9229
+ account,
9230
+ accountAddress,
9231
+ spenderAddress: quote.sourceBridgeAddress,
9232
+ currency: quote.rareTokenAddress,
9233
+ requiredAmount: quote.amount,
9234
+ autoApprove: params.autoApprove
9235
+ });
9236
+ const sendArgs = buildBridgeSendArgs({
9237
+ destinationBridgeInfo: getBridgeInfo(quote.destinationChain),
9238
+ distributionData: quote.distributionData
9239
+ });
9240
+ const { txHash, receipt, estimatedGas } = await runWithApprovalSideEffectAlert({
9241
+ operation: "bridge send",
9242
+ approvals: [{
9243
+ type: "erc20",
9244
+ approvalTxHash: approval.approvalTxHash,
9245
+ target: quote.rareTokenAddress,
9246
+ spender: quote.sourceBridgeAddress
9247
+ }],
9248
+ run: async () => {
9249
+ const gas = await estimateBridgeGas(publicClient, {
9250
+ account: accountAddress,
9251
+ sourceBridgeAddress: quote.sourceBridgeAddress,
9252
+ args: sendArgs,
9253
+ nativeFee: quote.nativeFee
9254
+ });
9255
+ const targetTxHash = await walletClient.writeContract({
9256
+ address: quote.sourceBridgeAddress,
9257
+ abi: rareBridgeAbi,
9258
+ functionName: "send",
9259
+ args: sendArgs,
9260
+ value: quote.nativeFee,
9261
+ account,
9262
+ chain: void 0
9263
+ });
9264
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
9265
+ return { txHash: targetTxHash, receipt: targetReceipt, estimatedGas: gas };
9266
+ }
9267
+ });
9268
+ return {
9269
+ ...quote,
9270
+ estimatedGas,
9271
+ txHash,
9272
+ receipt,
9273
+ approvalTxHash: approval.approvalTxHash,
9274
+ ccipExplorerUrl: buildCcipExplorerUrl(txHash)
9275
+ };
9276
+ }
9277
+ async function buildBridgeQuote(publicClient, config, sourceChain, params, options = {}) {
9278
+ const routeValidation = validateBridgeRoute({
9279
+ sourceChain,
9280
+ destinationChain: params.destinationChain
9281
+ });
9282
+ if (!routeValidation.isValid) {
9283
+ throw new Error(routeValidation.errorMessage);
9284
+ }
9285
+ const sourceBridgeInfo = getBridgeInfo(sourceChain);
9286
+ const destinationBridgeInfo = getBridgeInfo(params.destinationChain);
9287
+ const recipient = resolveRecipient(params.recipient, config);
9288
+ const amount = toPositiveWei(params.amount, "amount");
9289
+ const distributionData = encodeBridgeDistribution({ recipient, amount });
9290
+ const args = buildBridgeSendArgs({
9291
+ destinationBridgeInfo,
9292
+ distributionData
9293
+ });
9294
+ const nativeFee = await publicClient.readContract({
9295
+ address: sourceBridgeInfo.rareBridgeAddress,
9296
+ abi: rareBridgeAbi,
9297
+ functionName: "getFee",
9298
+ args
9299
+ });
9300
+ const estimatedGas = options.estimateGas === false ? void 0 : await estimateBridgeGas(publicClient, {
9301
+ account: getConfiguredAccountAddress(config),
9302
+ sourceBridgeAddress: sourceBridgeInfo.rareBridgeAddress,
9303
+ args,
9304
+ nativeFee
9305
+ });
9306
+ return {
9307
+ sourceChain,
9308
+ sourceChainId: sourceBridgeInfo.chainId,
9309
+ destinationChain: params.destinationChain,
9310
+ destinationChainId: destinationBridgeInfo.chainId,
9311
+ sourceBridgeAddress: sourceBridgeInfo.rareBridgeAddress,
9312
+ destinationBridgeAddress: destinationBridgeInfo.rareBridgeAddress,
9313
+ rareTokenAddress: sourceBridgeInfo.rareTokenAddress,
9314
+ destinationCcipChainSelector: destinationBridgeInfo.ccipChainSelector,
9315
+ amount,
9316
+ recipient,
9317
+ distributionData,
9318
+ nativeFee,
9319
+ estimatedGas
9320
+ };
9321
+ }
9322
+ function resolveRecipient(recipient, config) {
9323
+ const resolved = recipient ?? getConfiguredAccountAddress(config);
9324
+ if (resolved === void 0) {
9325
+ throw new Error("No recipient available for bridge quote. Pass params.recipient or provide config.account/walletClient with an account.");
9326
+ }
9327
+ return resolved;
9328
+ }
9329
+ async function estimateBridgeGas(publicClient, params) {
9330
+ if (params.account === void 0) {
9331
+ return void 0;
9332
+ }
9333
+ return publicClient.estimateGas({
9334
+ account: params.account,
9335
+ to: params.sourceBridgeAddress,
9336
+ data: encodeFunctionData({
9337
+ abi: rareBridgeAbi,
9338
+ functionName: "send",
9339
+ args: params.args
9340
+ }),
9341
+ value: params.nativeFee
9342
+ });
9343
+ }
9344
+
8707
9345
  // src/contracts/abis/liquid-router.ts
8708
9346
  var liquidRouterAbi = [
8709
9347
  {
@@ -9090,7 +9728,7 @@ async function quoteRouteSteps(publicClient, quoterAddress, routeSteps, currentA
9090
9728
 
9091
9729
  // src/swap/route-encoding.ts
9092
9730
  import {
9093
- encodeAbiParameters,
9731
+ encodeAbiParameters as encodeAbiParameters2,
9094
9732
  encodePacked as encodePacked2,
9095
9733
  getAddress as getAddress7,
9096
9734
  parseAbiParameters
@@ -9202,13 +9840,13 @@ function getV4ExecutionMode(v4BlockStartIndex, nextIndex, routeLength) {
9202
9840
  };
9203
9841
  }
9204
9842
  function encodeWrapEth(recipient, amount) {
9205
- return encodeAbiParameters(
9843
+ return encodeAbiParameters2(
9206
9844
  parseAbiParameters("address recipient, uint256 amount"),
9207
9845
  [recipient, amount]
9208
9846
  );
9209
9847
  }
9210
9848
  function encodeUnwrapWeth(recipient, amountMinimum) {
9211
- return encodeAbiParameters(
9849
+ return encodeAbiParameters2(
9212
9850
  parseAbiParameters("address recipient, uint256 amountMinimum"),
9213
9851
  [recipient, amountMinimum]
9214
9852
  );
@@ -9228,23 +9866,23 @@ function encodeV4ExactIn({
9228
9866
  step.poolKey.hooks,
9229
9867
  "0x"
9230
9868
  ]);
9231
- const swapParams = encodeAbiParameters(
9869
+ const swapParams = encodeAbiParameters2(
9232
9870
  parseAbiParameters("(address,(address,uint24,int24,address,bytes)[],uint128,uint128)"),
9233
9871
  [[currencyIn, pathKeysArray, amountIn, minAmountOut]]
9234
9872
  );
9235
9873
  const settleAction = executionMode.inputSource === "user" ? V4_ACTIONS.SETTLE_ALL : V4_ACTIONS.SETTLE;
9236
- const settleParams = executionMode.inputSource === "user" ? encodeAbiParameters(
9874
+ const settleParams = executionMode.inputSource === "user" ? encodeAbiParameters2(
9237
9875
  parseAbiParameters("address currency, uint128 maxAmount"),
9238
9876
  [currencyIn, amountIn]
9239
- ) : encodeAbiParameters(
9877
+ ) : encodeAbiParameters2(
9240
9878
  parseAbiParameters("address currency, uint256 amount, bool payerIsUser"),
9241
9879
  [currencyIn, ROUTER_AMOUNT_CONSTANTS.contractBalance, false]
9242
9880
  );
9243
9881
  const takeAction = executionMode.outputTarget === "user" ? V4_ACTIONS.TAKE_ALL : V4_ACTIONS.TAKE;
9244
- const takeParams = executionMode.outputTarget === "user" ? encodeAbiParameters(
9882
+ const takeParams = executionMode.outputTarget === "user" ? encodeAbiParameters2(
9245
9883
  parseAbiParameters("address currency, uint128 minAmount"),
9246
9884
  [currencyOut, minAmountOut]
9247
- ) : encodeAbiParameters(
9885
+ ) : encodeAbiParameters2(
9248
9886
  parseAbiParameters("address currency, address recipient, uint256 amount"),
9249
9887
  [currencyOut, ROUTER_RECIPIENTS.addressThis, ROUTER_AMOUNT_CONSTANTS.openDelta]
9250
9888
  );
@@ -9257,7 +9895,7 @@ function encodeV4ExactIn({
9257
9895
  ["uint8", "uint8", "uint8"],
9258
9896
  [settleAction, V4_ACTIONS.SWAP_EXACT_IN_SINGLE, takeAction]
9259
9897
  );
9260
- return encodeAbiParameters(
9898
+ return encodeAbiParameters2(
9261
9899
  parseAbiParameters("bytes actions, bytes[] params"),
9262
9900
  [
9263
9901
  actions2,
@@ -9273,7 +9911,7 @@ function encodeV4ExactIn({
9273
9911
  ["uint8", "uint8", "uint8"],
9274
9912
  [V4_ACTIONS.SWAP_EXACT_IN, settleAction, takeAction]
9275
9913
  );
9276
- return encodeAbiParameters(
9914
+ return encodeAbiParameters2(
9277
9915
  parseAbiParameters("bytes actions, bytes[] params"),
9278
9916
  [actions, [swapParams, settleParams, takeParams]]
9279
9917
  );
@@ -9292,7 +9930,7 @@ function encodeV4ExactInSingle(step, amountIn, minAmountOut) {
9292
9930
  minAmountOut,
9293
9931
  "0x"
9294
9932
  ];
9295
- return encodeAbiParameters(
9933
+ return encodeAbiParameters2(
9296
9934
  parseAbiParameters("((address,address,uint24,int24,address),bool,uint128,uint128,bytes)"),
9297
9935
  [swapExactInSingleTuple]
9298
9936
  );
@@ -9899,7 +10537,7 @@ async function executeRawRouterBuy(params) {
9899
10537
  const minAmountOutInput = requireInput(params.minAmountOut, "minAmountOut");
9900
10538
  const ethAmount = toWei(amountIn);
9901
10539
  const minTokensOut = await toTokenAmount(params.publicClient, params.token, minAmountOutInput, "minAmountOut");
9902
- const txHash = await walletClient.writeContract({
10540
+ const targetTxHash = await walletClient.writeContract({
9903
10541
  address: router,
9904
10542
  abi: liquidRouterAbi,
9905
10543
  functionName: "buy",
@@ -9908,8 +10546,8 @@ async function executeRawRouterBuy(params) {
9908
10546
  chain: void 0,
9909
10547
  value: ethAmount
9910
10548
  });
9911
- const receipt = await params.publicClient.waitForTransactionReceipt({ hash: txHash });
9912
- return { txHash, receipt, minAmountOut: minTokensOut };
10549
+ const targetReceipt = await params.publicClient.waitForTransactionReceipt({ hash: targetTxHash });
10550
+ return { txHash: targetTxHash, receipt: targetReceipt, minAmountOut: minTokensOut };
9913
10551
  }
9914
10552
  async function executeRawRouterSell(params) {
9915
10553
  const { walletClient, account, accountAddress } = requireWallet(params.config);
@@ -9919,25 +10557,37 @@ async function executeRawRouterSell(params) {
9919
10557
  const minAmountOutInput = requireInput(params.minAmountOut, "minAmountOut");
9920
10558
  const tokenAmount = await toTokenAmount(params.publicClient, params.token, amountIn, "amountIn");
9921
10559
  const minEthOut = toWei(minAmountOutInput);
9922
- await ensureTokenAllowance(params.publicClient, walletClient, account, accountAddress, params.token, router, tokenAmount);
9923
- const txHash = await walletClient.writeContract({
9924
- address: router,
9925
- abi: liquidRouterAbi,
9926
- functionName: "sell",
9927
- args: [
9928
- params.token,
9929
- tokenAmount,
9930
- params.recipient ?? accountAddress,
9931
- minEthOut,
9932
- params.commands,
9933
- [...params.inputs],
9934
- resolveDeadline(params.deadline)
9935
- ],
9936
- account,
9937
- chain: void 0
10560
+ const approvalTxHash = await ensureTokenAllowance(params.publicClient, walletClient, account, accountAddress, params.token, router, tokenAmount);
10561
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
10562
+ operation: "swap sell",
10563
+ approvals: [{
10564
+ type: "erc20",
10565
+ approvalTxHash,
10566
+ target: params.token,
10567
+ spender: router
10568
+ }],
10569
+ run: async () => {
10570
+ const targetTxHash = await walletClient.writeContract({
10571
+ address: router,
10572
+ abi: liquidRouterAbi,
10573
+ functionName: "sell",
10574
+ args: [
10575
+ params.token,
10576
+ tokenAmount,
10577
+ params.recipient ?? accountAddress,
10578
+ minEthOut,
10579
+ params.commands,
10580
+ [...params.inputs],
10581
+ resolveDeadline(params.deadline)
10582
+ ],
10583
+ account,
10584
+ chain: void 0
10585
+ });
10586
+ const targetReceipt = await params.publicClient.waitForTransactionReceipt({ hash: targetTxHash });
10587
+ return { txHash: targetTxHash, receipt: targetReceipt };
10588
+ }
9938
10589
  });
9939
- const receipt = await params.publicClient.waitForTransactionReceipt({ hash: txHash });
9940
- return { txHash, receipt, minAmountOut: minEthOut, tokenAmount };
10590
+ return { txHash, receipt, minAmountOut: minEthOut, tokenAmount, approvalTxHash };
9941
10591
  }
9942
10592
  function isRawTokenTradeParams(params) {
9943
10593
  return params.route === "raw";
@@ -9981,28 +10631,38 @@ function createSwapNamespace(config, chain, chainId, addresses) {
9981
10631
  validateRouterPayload(params.commands, params.inputs);
9982
10632
  const amountIn = await toTokenAmount(publicClient, params.tokenIn, params.amountIn, "amountIn");
9983
10633
  const minAmountOut = await toTokenAmount(publicClient, params.tokenOut, params.minAmountOut, "minAmountOut");
9984
- if (params.tokenIn !== ETH_ADDRESS) {
9985
- await ensureTokenAllowance(publicClient, walletClient, account, accountAddress, params.tokenIn, router, amountIn);
9986
- }
9987
- const txHash = await walletClient.writeContract({
9988
- address: router,
9989
- abi: liquidRouterAbi,
9990
- functionName: "swap",
9991
- args: [
9992
- params.tokenIn,
9993
- amountIn,
9994
- params.tokenOut,
9995
- params.recipient ?? accountAddress,
9996
- minAmountOut,
9997
- params.commands,
9998
- [...params.inputs],
9999
- resolveDeadline(params.deadline)
10000
- ],
10001
- account,
10002
- chain: void 0,
10003
- value: params.tokenIn === ETH_ADDRESS ? amountIn : void 0
10634
+ const approvalTxHash = params.tokenIn === ETH_ADDRESS ? void 0 : await ensureTokenAllowance(publicClient, walletClient, account, accountAddress, params.tokenIn, router, amountIn);
10635
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
10636
+ operation: "swap tokens",
10637
+ approvals: [{
10638
+ type: "erc20",
10639
+ approvalTxHash,
10640
+ target: params.tokenIn,
10641
+ spender: router
10642
+ }],
10643
+ run: async () => {
10644
+ const targetTxHash = await walletClient.writeContract({
10645
+ address: router,
10646
+ abi: liquidRouterAbi,
10647
+ functionName: "swap",
10648
+ args: [
10649
+ params.tokenIn,
10650
+ amountIn,
10651
+ params.tokenOut,
10652
+ params.recipient ?? accountAddress,
10653
+ minAmountOut,
10654
+ params.commands,
10655
+ [...params.inputs],
10656
+ resolveDeadline(params.deadline)
10657
+ ],
10658
+ account,
10659
+ chain: void 0,
10660
+ value: params.tokenIn === ETH_ADDRESS ? amountIn : void 0
10661
+ });
10662
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
10663
+ return { txHash: targetTxHash, receipt: targetReceipt };
10664
+ }
10004
10665
  });
10005
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
10006
10666
  return { txHash, receipt };
10007
10667
  },
10008
10668
  async quoteBuyToken(params) {
@@ -10069,7 +10729,7 @@ function createSwapNamespace(config, chain, chainId, addresses) {
10069
10729
  });
10070
10730
  if (quoteDetails.kind === "local") {
10071
10731
  const router = requireConfiguredAddress(addresses.swapRouter, "Liquid router", chain);
10072
- const txHash = await walletClient.writeContract({
10732
+ const targetTxHash = await walletClient.writeContract({
10073
10733
  address: router,
10074
10734
  abi: liquidRouterAbi,
10075
10735
  functionName: "buy",
@@ -10085,10 +10745,10 @@ function createSwapNamespace(config, chain, chainId, addresses) {
10085
10745
  chain: void 0,
10086
10746
  value: quoteDetails.quote.amountIn
10087
10747
  });
10088
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
10748
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
10089
10749
  return {
10090
- txHash,
10091
- receipt,
10750
+ txHash: targetTxHash,
10751
+ receipt: targetReceipt,
10092
10752
  estimatedAmountOut: quoteDetails.quote.estimatedAmountOut,
10093
10753
  minAmountOut: quoteDetails.quote.minAmountOut,
10094
10754
  routeSource: quoteDetails.quote.routeSource,
@@ -10180,24 +10840,36 @@ function createSwapNamespace(config, chain, chainId, addresses) {
10180
10840
  const router = requireConfiguredAddress(addresses.swapRouter, "Liquid router", chain);
10181
10841
  const amountIn = requireInput(params.amountIn, "amountIn");
10182
10842
  const tokenAmount = await toTokenAmount(publicClient, params.token, amountIn, "amountIn");
10183
- await ensureTokenAllowance(publicClient, walletClient, account, accountAddress, params.token, router, tokenAmount);
10184
- const txHash = await walletClient.writeContract({
10185
- address: router,
10186
- abi: liquidRouterAbi,
10187
- functionName: "sell",
10188
- args: [
10189
- params.token,
10190
- tokenAmount,
10191
- params.recipient ?? accountAddress,
10192
- quoteDetails.quote.minAmountOut,
10193
- quoteDetails.quote.commands,
10194
- [...quoteDetails.quote.inputs],
10195
- resolveDeadline(params.deadline)
10196
- ],
10197
- account,
10198
- chain: void 0
10843
+ const approvalTxHash2 = await ensureTokenAllowance(publicClient, walletClient, account, accountAddress, params.token, router, tokenAmount);
10844
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
10845
+ operation: "sell token",
10846
+ approvals: [{
10847
+ type: "erc20",
10848
+ approvalTxHash: approvalTxHash2,
10849
+ target: params.token,
10850
+ spender: router
10851
+ }],
10852
+ run: async () => {
10853
+ const targetTxHash = await walletClient.writeContract({
10854
+ address: router,
10855
+ abi: liquidRouterAbi,
10856
+ functionName: "sell",
10857
+ args: [
10858
+ params.token,
10859
+ tokenAmount,
10860
+ params.recipient ?? accountAddress,
10861
+ quoteDetails.quote.minAmountOut,
10862
+ quoteDetails.quote.commands,
10863
+ [...quoteDetails.quote.inputs],
10864
+ resolveDeadline(params.deadline)
10865
+ ],
10866
+ account,
10867
+ chain: void 0
10868
+ });
10869
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
10870
+ return { txHash: targetTxHash, receipt: targetReceipt };
10871
+ }
10199
10872
  });
10200
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
10201
10873
  return {
10202
10874
  txHash,
10203
10875
  receipt,
@@ -10206,7 +10878,8 @@ function createSwapNamespace(config, chain, chainId, addresses) {
10206
10878
  routeSource: quoteDetails.quote.routeSource,
10207
10879
  execution: quoteDetails.quote.execution,
10208
10880
  commands: quoteDetails.quote.commands,
10209
- inputs: quoteDetails.quote.inputs
10881
+ inputs: quoteDetails.quote.inputs,
10882
+ approvalTxHash: approvalTxHash2
10210
10883
  };
10211
10884
  }
10212
10885
  const approval = await requestUniswapApproval({
@@ -10225,14 +10898,33 @@ function createSwapNamespace(config, chain, chainId, addresses) {
10225
10898
  accountAddress,
10226
10899
  chainId
10227
10900
  })).txHash : void 0;
10228
- const swapResponse = await requestUniswapSwap({
10229
- apiKey: quoteDetails.apiKey,
10230
- quote: quoteDetails.rawQuote,
10231
- deadline: uniswapDeadline
10232
- });
10233
- const sent = await sendPreparedTransaction(publicClient, walletClient, account, swapResponse.swap, {
10234
- accountAddress,
10235
- chainId
10901
+ const sent = await runWithApprovalSideEffectAlert({
10902
+ operation: "sell token",
10903
+ approvals: [
10904
+ {
10905
+ type: "erc20-reset",
10906
+ approvalTxHash: approvalResetTxHash,
10907
+ target: params.token,
10908
+ spender: approval.cancel?.to
10909
+ },
10910
+ {
10911
+ type: "erc20",
10912
+ approvalTxHash,
10913
+ target: params.token,
10914
+ spender: approval.approval?.to
10915
+ }
10916
+ ],
10917
+ run: async () => {
10918
+ const swapResponse = await requestUniswapSwap({
10919
+ apiKey: quoteDetails.apiKey,
10920
+ quote: quoteDetails.rawQuote,
10921
+ deadline: uniswapDeadline
10922
+ });
10923
+ return sendPreparedTransaction(publicClient, walletClient, account, swapResponse.swap, {
10924
+ accountAddress,
10925
+ chainId
10926
+ });
10927
+ }
10236
10928
  });
10237
10929
  return {
10238
10930
  ...sent,
@@ -10251,7 +10943,7 @@ function createSwapNamespace(config, chain, chainId, addresses) {
10251
10943
  const { walletClient, account, accountAddress } = requireWallet(config);
10252
10944
  const router = requireConfiguredAddress(addresses.swapRouter, "Liquid router", chain);
10253
10945
  const quote = await buildBuyRareQuote(publicClient, chain, addresses, params);
10254
- const txHash = await walletClient.writeContract({
10946
+ const targetTxHash = await walletClient.writeContract({
10255
10947
  address: router,
10256
10948
  abi: liquidRouterAbi,
10257
10949
  functionName: "buy",
@@ -10260,10 +10952,10 @@ function createSwapNamespace(config, chain, chainId, addresses) {
10260
10952
  chain: void 0,
10261
10953
  value: quote.ethAmount
10262
10954
  });
10263
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
10955
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
10264
10956
  return {
10265
- txHash,
10266
- receipt,
10957
+ txHash: targetTxHash,
10958
+ receipt: targetReceipt,
10267
10959
  estimatedRareOut: quote.estimatedRareOut,
10268
10960
  minRareOut: quote.minRareOut,
10269
10961
  commands: quote.commands,
@@ -10599,9 +11291,32 @@ var rareMinterAbi = [
10599
11291
  ];
10600
11292
 
10601
11293
  // src/sdk/collection-core.ts
11294
+ var lazySovereignCollectionContractTypes = [
11295
+ "lazy",
11296
+ "lazy-royalty-guard",
11297
+ "lazy-deadman-royalty-guard"
11298
+ ];
10602
11299
  var defaultRoyaltyInfoSalePrice = 10000n;
11300
+ function normalizeLazySovereignCollectionContractType(input) {
11301
+ if (input === void 0) {
11302
+ return void 0;
11303
+ }
11304
+ const normalized = input.trim().toLowerCase();
11305
+ if (normalized === "lazy" || normalized === "standard" || normalized === "lazy-sovereign" || normalized === "lazy-sovereign-nft") {
11306
+ return "lazy";
11307
+ }
11308
+ if (normalized === "lazy-royalty-guard" || normalized === "royalty-guard") {
11309
+ return "lazy-royalty-guard";
11310
+ }
11311
+ if (normalized === "lazy-deadman-royalty-guard" || normalized === "lazy-royalty-guard-deadman" || normalized === "deadman-royalty-guard" || normalized === "royalty-guard-deadman" || normalized === "deadman") {
11312
+ return "lazy-deadman-royalty-guard";
11313
+ }
11314
+ throw new Error(
11315
+ `Unsupported Lazy Sovereign collection contract type "${input}". Supported: ${lazySovereignCollectionContractTypes.join(", ")}.`
11316
+ );
11317
+ }
10603
11318
  function planCreateLazySovereignCollection(params) {
10604
- const contractType = params.contractType ?? "lazy";
11319
+ const contractType = normalizeLazySovereignCollectionContractType(params.contractType) ?? "lazy";
10605
11320
  return {
10606
11321
  name: params.name,
10607
11322
  symbol: params.symbol,
@@ -11428,10 +12143,8 @@ async function readReleaseCollectionOwner(publicClient, contract) {
11428
12143
  );
11429
12144
  }
11430
12145
  }
11431
- async function assertConfigurableReleaseContract(opts) {
12146
+ async function assertReleaseMinterCanMint(opts) {
11432
12147
  const { publicClient, contract, accountAddress, rareMinter } = opts;
11433
- const owner = await readReleaseCollectionOwner(publicClient, contract);
11434
- assertReleaseContractOwner({ contract, accountAddress, owner });
11435
12148
  try {
11436
12149
  await publicClient.simulateContract({
11437
12150
  address: contract,
@@ -11797,6 +12510,11 @@ function createReleaseNamespace(publicClient, config, chain, addresses) {
11797
12510
  currencyDecimals: currencyDecimals2,
11798
12511
  nowSeconds: currentUnixTimestamp3()
11799
12512
  });
12513
+ await assertCollectionOwnerForReleaseWrite({
12514
+ publicClient,
12515
+ contract: plan.contract,
12516
+ accountAddress
12517
+ });
11800
12518
  const approvalTxHash = await approveReleaseMinterIfNeeded({
11801
12519
  publicClient,
11802
12520
  walletClient,
@@ -11805,29 +12523,41 @@ function createReleaseNamespace(publicClient, config, chain, addresses) {
11805
12523
  minter: rareMinter,
11806
12524
  autoApprove: params.autoApprove
11807
12525
  });
11808
- await assertConfigurableReleaseContract({
11809
- publicClient,
11810
- contract: plan.contract,
11811
- accountAddress,
11812
- rareMinter
11813
- });
11814
- const txHash = await walletClient.writeContract({
11815
- address: rareMinter,
11816
- abi: rareMinterAbi,
11817
- functionName: "prepareMintDirectSale",
11818
- args: [
11819
- plan.contract,
11820
- plan.currencyAddress,
11821
- plan.price,
11822
- plan.startTime,
11823
- plan.maxMints,
11824
- plan.splitRecipients,
11825
- plan.splitRatios
11826
- ],
11827
- account,
11828
- chain: void 0
12526
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
12527
+ operation: "release configure",
12528
+ approvals: [{
12529
+ type: "minter",
12530
+ approvalTxHash,
12531
+ target: plan.contract,
12532
+ minter: rareMinter
12533
+ }],
12534
+ run: async () => {
12535
+ await assertReleaseMinterCanMint({
12536
+ publicClient,
12537
+ contract: plan.contract,
12538
+ accountAddress,
12539
+ rareMinter
12540
+ });
12541
+ const configureTxHash = await walletClient.writeContract({
12542
+ address: rareMinter,
12543
+ abi: rareMinterAbi,
12544
+ functionName: "prepareMintDirectSale",
12545
+ args: [
12546
+ plan.contract,
12547
+ plan.currencyAddress,
12548
+ plan.price,
12549
+ plan.startTime,
12550
+ plan.maxMints,
12551
+ plan.splitRecipients,
12552
+ plan.splitRatios
12553
+ ],
12554
+ account,
12555
+ chain: void 0
12556
+ });
12557
+ const configureReceipt = await publicClient.waitForTransactionReceipt({ hash: configureTxHash });
12558
+ return { txHash: configureTxHash, receipt: configureReceipt };
12559
+ }
11829
12560
  });
11830
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
11831
12561
  return {
11832
12562
  txHash,
11833
12563
  receipt,
@@ -11876,26 +12606,38 @@ function createReleaseNamespace(publicClient, config, chain, addresses) {
11876
12606
  amount: mint.totalPrice,
11877
12607
  autoApprove: plan.autoApprove
11878
12608
  });
11879
- const txHash = await walletClient.writeContract({
11880
- address: rareMinter,
11881
- abi: rareMinterAbi,
11882
- functionName: "mintDirectSale",
11883
- args: [
11884
- mint.contract,
11885
- mint.currency,
11886
- mint.price,
11887
- mint.quantity,
11888
- mint.proof
11889
- ],
11890
- account,
11891
- chain: void 0,
11892
- value: payment.value
11893
- });
11894
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
11895
- const tokenRange = readMintDirectSaleTokenRange({
11896
- receipt,
11897
- contract: mint.contract,
11898
- buyer: accountAddress
12609
+ const { txHash, receipt, tokenRange } = await runWithApprovalSideEffectAlert({
12610
+ operation: "release mint",
12611
+ approvals: [{
12612
+ type: "erc20",
12613
+ approvalTxHash: payment.approvalTxHash,
12614
+ target: mint.currency,
12615
+ spender: rareMinter
12616
+ }],
12617
+ run: async () => {
12618
+ const targetTxHash = await walletClient.writeContract({
12619
+ address: rareMinter,
12620
+ abi: rareMinterAbi,
12621
+ functionName: "mintDirectSale",
12622
+ args: [
12623
+ mint.contract,
12624
+ mint.currency,
12625
+ mint.price,
12626
+ mint.quantity,
12627
+ mint.proof
12628
+ ],
12629
+ account,
12630
+ chain: void 0,
12631
+ value: payment.value
12632
+ });
12633
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
12634
+ const mintedTokenRange = readMintDirectSaleTokenRange({
12635
+ receipt: targetReceipt,
12636
+ contract: mint.contract,
12637
+ buyer: accountAddress
12638
+ });
12639
+ return { txHash: targetTxHash, receipt: targetReceipt, tokenRange: mintedTokenRange };
12640
+ }
11899
12641
  });
11900
12642
  return {
11901
12643
  txHash,
@@ -12971,10 +13713,14 @@ function addressLeaf(address) {
12971
13713
  return hexBuffer(keccak2563(address));
12972
13714
  }
12973
13715
  function parseBytes32(value, field) {
12974
- if (!isHex5(value) || value.length !== 66) {
13716
+ if (!isHex5(value, { strict: true }) || value.length !== 66) {
12975
13717
  throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
12976
13718
  }
12977
- return value;
13719
+ const normalized = value.toLowerCase();
13720
+ if (!isHex5(normalized, { strict: true }) || normalized.length !== 66) {
13721
+ throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
13722
+ }
13723
+ return normalized;
12978
13724
  }
12979
13725
  function parseBytes32Array(values, field) {
12980
13726
  return values.map((value, index) => parseBytes32(value, `${field}[${index}]`));
@@ -13050,14 +13796,15 @@ function buildMerkleProofArtifact(artifact, contract, tokenId, buyer) {
13050
13796
  const { tree, root } = buildBatchListingTree(
13051
13797
  artifact.tokens.map((token) => ({ contract: token.contract, tokenId: token.tokenId }))
13052
13798
  );
13053
- if (root !== artifact.root) {
13799
+ const artifactRoot = parseBytes32(artifact.root, "artifact.root");
13800
+ if (root !== artifactRoot) {
13054
13801
  throw new Error(
13055
13802
  `Recomputed NFT tree root (${root}) does not match artifact root (${artifact.root}). Artifact is corrupt or tree encoding has drifted.`
13056
13803
  );
13057
13804
  }
13058
13805
  const allowListProofFields = buildAllowListProofFields(artifact, buyer);
13059
13806
  return {
13060
- root: artifact.root,
13807
+ root: artifactRoot,
13061
13808
  contract: contractChecksum,
13062
13809
  tokenId: tokenIdBig.toString(),
13063
13810
  proof: getTokenProof(tree, contractChecksum, tokenIdBig),
@@ -13078,7 +13825,8 @@ function buildAllowListProofFields(artifact, buyer) {
13078
13825
  throw new Error(`Buyer ${buyerChecksum} is not in the allowlist`);
13079
13826
  }
13080
13827
  const { tree, root } = buildAllowListTree(artifact.allowList.addresses);
13081
- if (root !== artifact.allowList.root) {
13828
+ const artifactAllowListRoot = parseBytes32(artifact.allowList.root, "allowList.root");
13829
+ if (root !== artifactAllowListRoot) {
13082
13830
  throw new Error(
13083
13831
  `Recomputed allowlist root (${root}) does not match artifact (${artifact.allowList.root})`
13084
13832
  );
@@ -13179,6 +13927,7 @@ function createRareClient(config) {
13179
13927
  contracts: {
13180
13928
  factory: addresses.factory,
13181
13929
  auction: addresses.auction,
13930
+ rareBridge: addresses.rareBridge,
13182
13931
  sovereignFactory: addresses.sovereignFactory,
13183
13932
  lazySovereignFactory: addresses.lazySovereignFactory,
13184
13933
  rareMinter: addresses.rareMinter,
@@ -13194,6 +13943,7 @@ function createRareClient(config) {
13194
13943
  v4Quoter: addresses.v4Quoter
13195
13944
  },
13196
13945
  liquidEdition: createLiquidNamespace(config, chain, addresses),
13946
+ bridge: createBridgeNamespace(publicClient, config, chain),
13197
13947
  swap: createSwapNamespace(config, chain, chainId, addresses),
13198
13948
  auction,
13199
13949
  offer,
@@ -13277,6 +14027,7 @@ function isRecord5(value) {
13277
14027
  return typeof value === "object" && value !== null;
13278
14028
  }
13279
14029
  export {
14030
+ ApprovalSideEffectError,
13280
14031
  NftApprovalRequiredError,
13281
14032
  PaymentApprovalRequiredError,
13282
14033
  createRareClient