@baseline-markets/sdk 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/index.cjs CHANGED
@@ -2,8 +2,13 @@
2
2
 
3
3
  var viem = require('viem');
4
4
  var chains = require('viem/chains');
5
+ var actions = require('viem/actions');
5
6
 
6
- // ../contracts/abis/external/chainlinkOracle.ts
7
+ var __defProp = Object.defineProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
7
12
 
8
13
  // ../contracts/abis/external/erc20.ts
9
14
  var erc20 = [
@@ -2742,6 +2747,8 @@ var externalAbis = {
2742
2747
  [chains.base.id]: {
2743
2748
  },
2744
2749
  [chains.baseSepolia.id]: {
2750
+ },
2751
+ [chains.hyperEvm.id]: {
2745
2752
  }
2746
2753
  });
2747
2754
  ({
@@ -2750,6 +2757,8 @@ var externalAbis = {
2750
2757
  [chains.base.id]: {
2751
2758
  },
2752
2759
  [chains.baseSepolia.id]: {
2760
+ },
2761
+ [chains.hyperEvm.id]: {
2753
2762
  }
2754
2763
  });
2755
2764
  var relayAddress = "0xc81Fd894C0acE037d133aF4886550aC8133568E8";
@@ -2765,6 +2774,10 @@ var addressBook_default = {
2765
2774
  [chains.baseSepolia.id]: {
2766
2775
  address: relayAddress,
2767
2776
  block: 40585325
2777
+ },
2778
+ [chains.hyperEvm.id]: {
2779
+ address: relayAddress,
2780
+ block: 37892152
2768
2781
  }
2769
2782
  };
2770
2783
  var ContractFactory = class {
@@ -2836,24 +2849,98 @@ var ContractFactory = class {
2836
2849
 
2837
2850
  // ../contracts/index.ts
2838
2851
  var supportedChainIds = Object.keys(addressBook_default).map(Number);
2852
+
2853
+ // src/calls/index.ts
2854
+ var calls_exports = {};
2855
+ __export(calls_exports, {
2856
+ MAX_UINT256: () => MAX_UINT256,
2857
+ WAD: () => WAD,
2858
+ ZERO_BYTES32: () => ZERO_BYTES32,
2859
+ approvalCalls: () => approvalCalls,
2860
+ buildLaunchCalls: () => buildLaunchCalls,
2861
+ createCallsApi: () => createCallsApi,
2862
+ encodeStandardLaunchCalls: () => encodeStandardLaunchCalls,
2863
+ encodeZrpLaunchCalls: () => encodeZrpLaunchCalls,
2864
+ serializeCalls: () => serializeCalls,
2865
+ simulateCalls: () => simulateCalls,
2866
+ validateLaunchCallInput: () => validateLaunchCallInput
2867
+ });
2868
+
2869
+ // src/utils/native.ts
2870
+ function shouldUseNative(explicit, config) {
2871
+ return explicit ?? !!config?.defaultUseNative;
2872
+ }
2873
+ function valueForNative(useNative, amount) {
2874
+ return useNative ? amount : void 0;
2875
+ }
2876
+ async function simulateCalls(publicClient, calls, opts) {
2877
+ const simulation = await publicClient.simulateCalls({
2878
+ account: opts?.account,
2879
+ calls
2880
+ });
2881
+ if (simulation.results.length !== calls.length) {
2882
+ throw new Error(
2883
+ `Call simulation returned ${simulation.results.length} results for ${calls.length} calls`
2884
+ );
2885
+ }
2886
+ return simulation.results.map((result, index) => {
2887
+ if (!result) {
2888
+ throw new Error(`Call simulation ${index} did not return a result`);
2889
+ }
2890
+ if (result.status === "failure") throw result.error;
2891
+ const call = calls[index];
2892
+ if (!call?.decode) return result.data;
2893
+ return call.decode(result.data);
2894
+ });
2895
+ }
2896
+ function contractCall(input) {
2897
+ return {
2898
+ to: input.to,
2899
+ data: viem.encodeFunctionData({
2900
+ abi: input.abi,
2901
+ functionName: input.functionName,
2902
+ args: input.args
2903
+ }),
2904
+ value: input.value,
2905
+ decode: (data) => {
2906
+ const result = viem.decodeFunctionResult({
2907
+ abi: input.abi,
2908
+ functionName: input.functionName,
2909
+ data
2910
+ });
2911
+ return input.mapResult ? input.mapResult(result) : result;
2912
+ }
2913
+ };
2914
+ }
2915
+ function serializeCalls(calls) {
2916
+ return calls.map((call) => ({
2917
+ to: call.to,
2918
+ data: call.data,
2919
+ value: viem.toHex(call.value ?? 0n)
2920
+ }));
2921
+ }
2922
+ var WAD = 10n ** 18n;
2923
+ var ZERO_BYTES32 = "0x0000000000000000000000000000000000000000000000000000000000000000";
2924
+ var DEFAULT_SWAP_FEE_PCT = WAD / 100n;
2925
+ var MIN_SWAP_FEE_PCT = 1500000000000000n;
2926
+ var MAX_SWAP_FEE_PCT = WAD / 2n;
2927
+ var MIN_TOTAL_SUPPLY = 10000n * WAD;
2928
+ var MAX_TOTAL_SUPPLY = 20282409603651670423947251286015n;
2929
+ var MIN_INVARIANT = 3n * WAD;
2839
2930
  function encodeBaseLaunchCalls(input) {
2840
2931
  return [
2841
- {
2932
+ contractCall({
2842
2933
  to: input.relay,
2843
- data: viem.encodeFunctionData({
2844
- abi: mercuryAbis.bFactory,
2845
- functionName: "createBToken",
2846
- args: [input.name, input.symbol, input.totalSupply, input.salt]
2847
- })
2848
- },
2849
- {
2934
+ abi: mercuryAbis.bFactory,
2935
+ functionName: "createBToken",
2936
+ args: [input.name, input.symbol, input.totalSupply, input.salt]
2937
+ }),
2938
+ contractCall({
2850
2939
  to: input.bToken,
2851
- data: viem.encodeFunctionData({
2852
- abi: externalAbis.erc20,
2853
- functionName: "approve",
2854
- args: [input.relay, input.bTokenApprovalAmount]
2855
- })
2856
- }
2940
+ abi: externalAbis.erc20,
2941
+ functionName: "approve",
2942
+ args: [input.relay, input.bTokenApprovalAmount]
2943
+ })
2857
2944
  ];
2858
2945
  }
2859
2946
  function encodeZrpLaunchCalls(input) {
@@ -2862,14 +2949,12 @@ function encodeZrpLaunchCalls(input) {
2862
2949
  ...input,
2863
2950
  bTokenApprovalAmount: input.params.initialPoolBTokens
2864
2951
  }),
2865
- {
2952
+ contractCall({
2866
2953
  to: input.relay,
2867
- data: viem.encodeFunctionData({
2868
- abi: mercuryAbis.bFactory,
2869
- functionName: "createPoolFromInvariant",
2870
- args: [input.params]
2871
- })
2872
- }
2954
+ abi: mercuryAbis.bFactory,
2955
+ functionName: "createPoolFromInvariant",
2956
+ args: [input.params]
2957
+ })
2873
2958
  ];
2874
2959
  }
2875
2960
  function encodeStandardLaunchCalls(input) {
@@ -2878,36 +2963,81 @@ function encodeStandardLaunchCalls(input) {
2878
2963
  ...input,
2879
2964
  bTokenApprovalAmount: input.params.initialPoolBTokens
2880
2965
  }),
2881
- {
2966
+ contractCall({
2882
2967
  to: input.reserve,
2883
- data: viem.encodeFunctionData({
2884
- abi: externalAbis.erc20,
2885
- functionName: "approve",
2886
- args: [input.relay, input.params.initialPoolReserves]
2887
- })
2888
- },
2889
- {
2968
+ abi: externalAbis.erc20,
2969
+ functionName: "approve",
2970
+ args: [input.relay, input.params.initialPoolReserves]
2971
+ }),
2972
+ contractCall({
2890
2973
  to: input.relay,
2891
- data: viem.encodeFunctionData({
2892
- abi: mercuryAbis.bFactory,
2893
- functionName: "createPool",
2894
- args: [input.params]
2895
- })
2896
- }
2974
+ abi: mercuryAbis.bFactory,
2975
+ functionName: "createPool",
2976
+ args: [input.params]
2977
+ })
2897
2978
  ];
2898
2979
  }
2899
-
2900
- // src/launch/constants.ts
2901
- var WAD = 10n ** 18n;
2902
- var ZERO_BYTES32 = "0x0000000000000000000000000000000000000000000000000000000000000000";
2903
- var DEFAULT_SWAP_FEE_PCT = WAD / 100n;
2904
- var MIN_SWAP_FEE_PCT = 1500000000000000n;
2905
- var MAX_SWAP_FEE_PCT = WAD / 2n;
2906
- var MIN_TOTAL_SUPPLY = 10000n * WAD;
2907
- var MAX_TOTAL_SUPPLY = 20282409603651670423947251286015n;
2908
- var MIN_INVARIANT = 3n * WAD;
2909
-
2910
- // src/launch/validate.ts
2980
+ function buildLaunchCalls(input) {
2981
+ const salt = normalizeSalt(input.salt);
2982
+ const { mode, swapFeePct, feeRecipient } = resolveLaunchDefaults(input);
2983
+ if (mode === "zrp") {
2984
+ const params2 = {
2985
+ bToken: input.bToken,
2986
+ initialPoolBTokens: input.initialPoolBTokens,
2987
+ reserve: input.reserve,
2988
+ initialInvariant: MIN_INVARIANT,
2989
+ creator: input.creator,
2990
+ feeRecipient,
2991
+ creatorFeePct: input.creatorFeePct,
2992
+ swapFeePct,
2993
+ createHook: true
2994
+ };
2995
+ return encodeZrpLaunchCalls({
2996
+ relay: input.relay,
2997
+ bToken: input.bToken,
2998
+ name: input.name,
2999
+ symbol: input.symbol,
3000
+ totalSupply: input.totalSupply,
3001
+ salt,
3002
+ params: params2
3003
+ });
3004
+ }
3005
+ const initialPoolReserves = input.initialPoolReserves ?? 0n;
3006
+ const circulatingSupply = input.totalSupply - input.initialPoolBTokens;
3007
+ const reservesWad = toWad(initialPoolReserves, input.reserveDecimals ?? 18);
3008
+ const circulatingWad = toWad(circulatingSupply, 18);
3009
+ const bookPrice = divWad(reservesWad, circulatingWad);
3010
+ const params = {
3011
+ bToken: input.bToken,
3012
+ initialPoolBTokens: input.initialPoolBTokens,
3013
+ reserve: input.reserve,
3014
+ initialPoolReserves,
3015
+ initialActivePrice: bookPrice + 1n,
3016
+ initialBLV: 0n,
3017
+ creator: input.creator,
3018
+ feeRecipient,
3019
+ creatorFeePct: input.creatorFeePct,
3020
+ swapFeePct,
3021
+ createHook: true,
3022
+ claimMerkleRoot: ZERO_BYTES32,
3023
+ initialCollateral: 0n,
3024
+ initialDebt: 0n
3025
+ };
3026
+ return encodeStandardLaunchCalls({
3027
+ relay: input.relay,
3028
+ bToken: input.bToken,
3029
+ reserve: input.reserve,
3030
+ name: input.name,
3031
+ symbol: input.symbol,
3032
+ totalSupply: input.totalSupply,
3033
+ salt,
3034
+ params
3035
+ });
3036
+ }
3037
+ function validateLaunchCallInput(input) {
3038
+ normalizeSalt(input.salt);
3039
+ resolveLaunchDefaults(input);
3040
+ }
2911
3041
  function normalizeSalt(salt) {
2912
3042
  if (!salt) return ZERO_BYTES32;
2913
3043
  if (!/^0x[a-fA-F0-9]{64}$/.test(salt)) {
@@ -2915,24 +3045,6 @@ function normalizeSalt(salt) {
2915
3045
  }
2916
3046
  return salt;
2917
3047
  }
2918
- function validateAddress(address, label) {
2919
- if (!viem.isAddress(address)) throw new Error(`${label} must be a valid address`);
2920
- }
2921
- function validateTokenText(name, symbol) {
2922
- if (name.trim().length === 0) throw new Error("name is required");
2923
- if (symbol.trim().length === 0) throw new Error("symbol is required");
2924
- if (new TextEncoder().encode(name).length > 30) {
2925
- throw new Error("name exceeds 30 bytes");
2926
- }
2927
- if (new TextEncoder().encode(symbol).length > 30) {
2928
- throw new Error("symbol exceeds 30 bytes");
2929
- }
2930
- }
2931
- function validateDecimals(decimals, label) {
2932
- if (!Number.isInteger(decimals) || decimals < 0 || decimals > 18) {
2933
- throw new Error(`${label} must be an integer between 0 and 18`);
2934
- }
2935
- }
2936
3048
  function resolveLaunchDefaults(input) {
2937
3049
  const mode = input.mode ?? "zrp";
2938
3050
  if (mode !== "zrp" && mode !== "standard") {
@@ -2982,66 +3094,23 @@ function resolveLaunchDefaults(input) {
2982
3094
  }
2983
3095
  return { mode, swapFeePct, feeRecipient };
2984
3096
  }
2985
-
2986
- // src/launch/calls.ts
2987
- function buildLaunchCalls(input) {
2988
- const salt = normalizeSalt(input.salt);
2989
- const { mode, swapFeePct, feeRecipient } = resolveLaunchDefaults(input);
2990
- if (mode === "zrp") {
2991
- const params2 = {
2992
- bToken: input.bToken,
2993
- initialPoolBTokens: input.initialPoolBTokens,
2994
- reserve: input.reserve,
2995
- initialInvariant: MIN_INVARIANT,
2996
- creator: input.creator,
2997
- feeRecipient,
2998
- creatorFeePct: input.creatorFeePct,
2999
- swapFeePct,
3000
- createHook: true
3001
- };
3002
- return encodeZrpLaunchCalls({
3003
- relay: input.relay,
3004
- bToken: input.bToken,
3005
- name: input.name,
3006
- symbol: input.symbol,
3007
- totalSupply: input.totalSupply,
3008
- salt,
3009
- params: params2
3010
- });
3097
+ function validateAddress(address, label) {
3098
+ if (!viem.isAddress(address)) throw new Error(`${label} must be a valid address`);
3099
+ }
3100
+ function validateTokenText(name, symbol) {
3101
+ if (name.trim().length === 0) throw new Error("name is required");
3102
+ if (symbol.trim().length === 0) throw new Error("symbol is required");
3103
+ if (new TextEncoder().encode(name).length > 30) {
3104
+ throw new Error("name exceeds 30 bytes");
3105
+ }
3106
+ if (new TextEncoder().encode(symbol).length > 30) {
3107
+ throw new Error("symbol exceeds 30 bytes");
3108
+ }
3109
+ }
3110
+ function validateDecimals(decimals, label) {
3111
+ if (!Number.isInteger(decimals) || decimals < 0 || decimals > 18) {
3112
+ throw new Error(`${label} must be an integer between 0 and 18`);
3011
3113
  }
3012
- const initialPoolReserves = input.initialPoolReserves ?? 0n;
3013
- const circulatingSupply = input.totalSupply - input.initialPoolBTokens;
3014
- const reservesWad = toWad(initialPoolReserves, input.reserveDecimals ?? 18);
3015
- const circulatingWad = toWad(circulatingSupply, 18);
3016
- const bookPrice = divWad(reservesWad, circulatingWad);
3017
- const initialActivePrice = bookPrice + 1n;
3018
- const initialBLV = 0n;
3019
- const params = {
3020
- bToken: input.bToken,
3021
- initialPoolBTokens: input.initialPoolBTokens,
3022
- reserve: input.reserve,
3023
- initialPoolReserves,
3024
- initialActivePrice,
3025
- initialBLV,
3026
- creator: input.creator,
3027
- feeRecipient,
3028
- creatorFeePct: input.creatorFeePct,
3029
- swapFeePct,
3030
- createHook: true,
3031
- claimMerkleRoot: ZERO_BYTES32,
3032
- initialCollateral: 0n,
3033
- initialDebt: 0n
3034
- };
3035
- return encodeStandardLaunchCalls({
3036
- relay: input.relay,
3037
- bToken: input.bToken,
3038
- reserve: input.reserve,
3039
- name: input.name,
3040
- symbol: input.symbol,
3041
- totalSupply: input.totalSupply,
3042
- salt,
3043
- params
3044
- });
3045
3114
  }
3046
3115
  function toWad(amount, decimals) {
3047
3116
  return amount * 10n ** BigInt(18 - decimals);
@@ -3049,9 +3118,157 @@ function toWad(amount, decimals) {
3049
3118
  function divWad(numerator, denominator) {
3050
3119
  return numerator * WAD / denominator;
3051
3120
  }
3052
- function validateLaunchCallInput(input) {
3053
- normalizeSalt(input.salt);
3054
- resolveLaunchDefaults(input);
3121
+
3122
+ // src/calls/index.ts
3123
+ var MAX_UINT256 = 2n ** 256n - 1n;
3124
+ function createCallsApi(input) {
3125
+ const relay = () => input.getRelay();
3126
+ return {
3127
+ launch: input.launch,
3128
+ factory: {
3129
+ createBToken: (name, symbol, totalSupply, salt) => contractCall({
3130
+ to: relay(),
3131
+ abi: mercuryAbis.bFactory,
3132
+ functionName: "createBToken",
3133
+ args: [name, symbol, totalSupply, salt]
3134
+ }),
3135
+ createPool: (params) => contractCall({
3136
+ to: relay(),
3137
+ abi: mercuryAbis.bFactory,
3138
+ functionName: "createPool",
3139
+ args: [params]
3140
+ }),
3141
+ createPoolFromInvariant: (params) => contractCall({
3142
+ to: relay(),
3143
+ abi: mercuryAbis.bFactory,
3144
+ functionName: "createPoolFromInvariant",
3145
+ args: [params]
3146
+ })
3147
+ },
3148
+ swap: {
3149
+ buyTokensExactOut: (bToken, amountOut, limitAmount, opts) => contractCall({
3150
+ to: relay(),
3151
+ abi: mercuryAbis.bSwap,
3152
+ functionName: "buyTokensExactOut",
3153
+ args: [bToken, amountOut, limitAmount],
3154
+ value: valueForNative(
3155
+ shouldUseNative(opts?.useNative, input.getConfig()),
3156
+ limitAmount
3157
+ )
3158
+ }),
3159
+ buyTokensExactIn: (bToken, amountIn, limitAmount) => contractCall({
3160
+ to: relay(),
3161
+ abi: mercuryAbis.bSwap,
3162
+ functionName: "buyTokensExactIn",
3163
+ args: [bToken, amountIn, limitAmount]
3164
+ }),
3165
+ sellTokensExactIn: (bToken, amountIn, limitAmount) => contractCall({
3166
+ to: relay(),
3167
+ abi: mercuryAbis.bSwap,
3168
+ functionName: "sellTokensExactIn",
3169
+ args: [bToken, amountIn, limitAmount]
3170
+ }),
3171
+ sellTokensExactOut: (bToken, amountOut, limitAmount) => contractCall({
3172
+ to: relay(),
3173
+ abi: mercuryAbis.bSwap,
3174
+ functionName: "sellTokensExactOut",
3175
+ args: [bToken, amountOut, limitAmount]
3176
+ })
3177
+ },
3178
+ staking: {
3179
+ deposit: (bToken, user, amount) => contractCall({
3180
+ to: relay(),
3181
+ abi: mercuryAbis.bStaking,
3182
+ functionName: "deposit",
3183
+ args: [bToken, user, amount]
3184
+ }),
3185
+ withdraw: (bToken, amount) => contractCall({
3186
+ to: relay(),
3187
+ abi: mercuryAbis.bStaking,
3188
+ functionName: "withdraw",
3189
+ args: [bToken, amount]
3190
+ }),
3191
+ claim: (bToken, user, asNative = false) => contractCall({
3192
+ to: relay(),
3193
+ abi: mercuryAbis.bStaking,
3194
+ functionName: "claim",
3195
+ args: [bToken, user, asNative]
3196
+ })
3197
+ },
3198
+ credit: {
3199
+ borrow: (bToken, amount, recipient, opts) => contractCall({
3200
+ to: relay(),
3201
+ abi: mercuryAbis.bCredit,
3202
+ functionName: opts?.outputNative ? "borrowNative" : "borrow",
3203
+ args: [bToken, amount, recipient]
3204
+ }),
3205
+ repay: (bToken, reservesIn, recipient, opts) => {
3206
+ const useNative = shouldUseNative(opts?.useNative, input.getConfig());
3207
+ return contractCall({
3208
+ to: relay(),
3209
+ abi: mercuryAbis.bCredit,
3210
+ functionName: useNative ? "repayWithNative" : "repay",
3211
+ args: useNative ? [bToken, recipient] : [bToken, reservesIn, recipient],
3212
+ value: useNative ? reservesIn : void 0
3213
+ });
3214
+ },
3215
+ leverage: (bToken, totalCollateral, collateralIn, maxSwapReservesIn) => contractCall({
3216
+ to: relay(),
3217
+ abi: mercuryAbis.bCredit,
3218
+ functionName: "leverage",
3219
+ args: [bToken, totalCollateral, collateralIn, maxSwapReservesIn]
3220
+ }),
3221
+ deleverage: (bToken, collateralToSell, minSwapReservesOut) => contractCall({
3222
+ to: relay(),
3223
+ abi: mercuryAbis.bCredit,
3224
+ functionName: "deleverage",
3225
+ args: [bToken, collateralToSell, minSwapReservesOut],
3226
+ mapResult: ([collateralRedeemed, debtRepaid, refund]) => ({
3227
+ collateralRedeemed,
3228
+ debtRepaid,
3229
+ refund
3230
+ })
3231
+ })
3232
+ },
3233
+ approval: {
3234
+ approve: (token, spender, amount) => contractCall({
3235
+ to: token,
3236
+ abi: externalAbis.erc20,
3237
+ functionName: "approve",
3238
+ args: [spender, amount]
3239
+ }),
3240
+ ensure: async (token, spender, required, opts) => {
3241
+ const owner = opts?.owner ?? input.getAccount();
3242
+ const policy = opts?.policy ?? input.getConfig()?.approvals ?? "infinite";
3243
+ const currentAllowance = await input.getAllowance(
3244
+ token,
3245
+ owner,
3246
+ spender
3247
+ );
3248
+ return approvalCalls({
3249
+ token,
3250
+ spender,
3251
+ required,
3252
+ currentAllowance,
3253
+ policy
3254
+ });
3255
+ }
3256
+ }
3257
+ };
3258
+ }
3259
+ function approvalCalls(input) {
3260
+ if (input.currentAllowance >= input.required) return [];
3261
+ return [
3262
+ contractCall({
3263
+ to: input.token,
3264
+ abi: externalAbis.erc20,
3265
+ functionName: "approve",
3266
+ args: [
3267
+ input.spender,
3268
+ input.policy === "infinite" ? MAX_UINT256 : input.required
3269
+ ]
3270
+ })
3271
+ ];
3055
3272
  }
3056
3273
  var SDKError = class extends Error {
3057
3274
  kind = "unknown";
@@ -3145,6 +3362,17 @@ async function requireWallet(wallet) {
3145
3362
  });
3146
3363
  return wallet;
3147
3364
  }
3365
+ function resolveWriteAccount(wallet, sender) {
3366
+ const walletAccount = wallet.account;
3367
+ if (!walletAccount) return sender;
3368
+ if (walletAccount.address.toLowerCase() !== sender.toLowerCase()) {
3369
+ throw new SDKError(
3370
+ `Wallet account ${walletAccount.address} cannot sign for requested account ${sender}`,
3371
+ { kind: "wallet" }
3372
+ );
3373
+ }
3374
+ return walletAccount;
3375
+ }
3148
3376
  async function simulateAndWrite({
3149
3377
  publicClient,
3150
3378
  walletClient,
@@ -3173,7 +3401,82 @@ async function simulateAndWrite({
3173
3401
  account: sender,
3174
3402
  value
3175
3403
  });
3176
- const hash = await wallet.writeContract(simulation.request);
3404
+ const hash = await wallet.writeContract({
3405
+ ...simulation.request,
3406
+ account: resolveWriteAccount(wallet, sender)
3407
+ });
3408
+ if (confirmations) {
3409
+ const receipt = await publicClient.waitForTransactionReceipt({
3410
+ hash,
3411
+ confirmations
3412
+ });
3413
+ if (receipt.status === "reverted") {
3414
+ throw new SDKError("Transaction reverted on-chain", {
3415
+ kind: "reverted",
3416
+ cause: { hash, receipt }
3417
+ });
3418
+ }
3419
+ }
3420
+ return hash;
3421
+ } catch (e) {
3422
+ onSimulateError?.(e);
3423
+ throw classifyTxError(e);
3424
+ }
3425
+ }
3426
+ async function executeCalls({
3427
+ publicClient,
3428
+ walletClient,
3429
+ calls,
3430
+ account,
3431
+ confirmations,
3432
+ onSimulateError
3433
+ }) {
3434
+ const wallet = await requireWallet(walletClient);
3435
+ const sender = account ?? wallet.account?.address;
3436
+ if (!sender) {
3437
+ throw new SDKError(
3438
+ "No account provided and wallet missing default account",
3439
+ {
3440
+ kind: "wallet"
3441
+ }
3442
+ );
3443
+ }
3444
+ if (calls.length === 0) {
3445
+ throw new SDKError("At least one call is required", { kind: "unknown" });
3446
+ }
3447
+ try {
3448
+ const simulation = await publicClient.simulateCalls({
3449
+ account: sender,
3450
+ calls
3451
+ });
3452
+ for (const [index, result] of simulation.results.entries()) {
3453
+ if (!result) {
3454
+ throw new SDKError(`Call simulation ${index} did not return a result`);
3455
+ }
3456
+ if (result.status === "failure") {
3457
+ const error = classifyTxError(result.error);
3458
+ if (error.kind === "unknown" && result.error instanceof Error) {
3459
+ throw new SDKError(result.error.message, {
3460
+ kind: "reverted",
3461
+ cause: result.error
3462
+ });
3463
+ }
3464
+ throw error;
3465
+ }
3466
+ }
3467
+ const { id } = await actions.sendCalls(wallet, {
3468
+ account: resolveWriteAccount(wallet, sender),
3469
+ calls,
3470
+ experimental_fallback: true
3471
+ });
3472
+ const status = await actions.waitForCallsStatus(wallet, {
3473
+ id,
3474
+ throwOnFailure: true
3475
+ });
3476
+ const hash = status.receipts?.[0]?.transactionHash;
3477
+ if (!hash) {
3478
+ throw new SDKError("Calls bundle did not return a transaction hash");
3479
+ }
3177
3480
  if (confirmations) {
3178
3481
  const receipt = await publicClient.waitForTransactionReceipt({
3179
3482
  hash,
@@ -3208,34 +3511,6 @@ async function getAllowance(client, token, owner, spender) {
3208
3511
  });
3209
3512
  return allowance;
3210
3513
  }
3211
- async function ensureAllowance(params) {
3212
- const current = await getAllowance(
3213
- params.publicClient,
3214
- params.token,
3215
- params.owner,
3216
- params.spender
3217
- );
3218
- if (current >= params.required) return;
3219
- const amount = params.policy === "infinite" ? 2n ** 256n - 1n : params.required;
3220
- await simulateAndWrite({
3221
- publicClient: params.publicClient,
3222
- walletClient: params.walletClient,
3223
- address: params.token,
3224
- abi: externalAbis.erc20,
3225
- functionName: "approve",
3226
- args: [params.spender, amount],
3227
- account: params.owner,
3228
- confirmations: params.confirmations
3229
- });
3230
- }
3231
-
3232
- // src/utils/native.ts
3233
- function shouldUseNative(explicit, config) {
3234
- return explicit ?? !!config?.defaultUseNative;
3235
- }
3236
- function valueForNative(useNative, amount) {
3237
- return useNative ? amount : void 0;
3238
- }
3239
3514
 
3240
3515
  // src/baseline-sdk.ts
3241
3516
  var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
@@ -3244,9 +3519,13 @@ var BaselineSDK = class _BaselineSDK {
3244
3519
  walletClient;
3245
3520
  config;
3246
3521
  readFactory;
3247
- calls = {
3522
+ calls = createCallsApi({
3523
+ getRelay: () => this.proxy,
3524
+ getConfig: () => this.config,
3525
+ getAccount: () => this.getAccount(),
3526
+ getAllowance: (token, owner, spender) => this.getAllowance(token, owner, spender),
3248
3527
  launch: (input, opts) => this.launchCalls(input, opts)
3249
- };
3528
+ });
3250
3529
  getAccount(opts) {
3251
3530
  const account = opts?.account ?? this.walletClient?.account?.address;
3252
3531
  if (!account) {
@@ -3297,7 +3576,10 @@ var BaselineSDK = class _BaselineSDK {
3297
3576
  account
3298
3577
  });
3299
3578
  const wallet = this.requireWallet();
3300
- const hash = await wallet.writeContract(request);
3579
+ const hash = await wallet.writeContract({
3580
+ ...request,
3581
+ account: resolveWriteAccount(wallet, account)
3582
+ });
3301
3583
  if (opts?.confirmations)
3302
3584
  await this.publicClient.waitForTransactionReceipt({
3303
3585
  hash,
@@ -3363,7 +3645,7 @@ var BaselineSDK = class _BaselineSDK {
3363
3645
  bToken: "0x0000000000000000000000000000000000000000",
3364
3646
  salt
3365
3647
  });
3366
- const bToken = await this.precomputeBTokenAddress({
3648
+ const bToken = opts?.precomputedBToken ?? await this.precomputeBTokenAddress({
3367
3649
  name: input.name,
3368
3650
  symbol: input.symbol,
3369
3651
  totalSupply: input.totalSupply,
@@ -3416,18 +3698,22 @@ var BaselineSDK = class _BaselineSDK {
3416
3698
  }
3417
3699
  // ---------- Swap execution ----------
3418
3700
  async buyTokensExactOut(bToken, amountOut, limitAmount, opts) {
3419
- const useNative = shouldUseNative(opts?.useNative, this.config);
3420
3701
  const account = this.getAccount(opts);
3421
- const value = valueForNative(useNative, limitAmount);
3702
+ const call = this.calls.swap.buyTokensExactOut(
3703
+ bToken,
3704
+ amountOut,
3705
+ limitAmount,
3706
+ opts
3707
+ );
3422
3708
  return simulateAndWrite({
3423
3709
  publicClient: this.publicClient,
3424
3710
  walletClient: this.walletClient,
3425
- address: this.proxy,
3711
+ address: call.to,
3426
3712
  abi: mercuryAbis.bSwap,
3427
3713
  functionName: "buyTokensExactOut",
3428
3714
  args: [bToken, amountOut, limitAmount],
3429
3715
  account,
3430
- value,
3716
+ value: call.value,
3431
3717
  confirmations: opts?.confirmations,
3432
3718
  onSimulateError: opts?.onSimulateError
3433
3719
  });
@@ -3492,23 +3778,20 @@ var BaselineSDK = class _BaselineSDK {
3492
3778
  }
3493
3779
  async withdraw(bToken, amount, opts) {
3494
3780
  const account = this.getAccount(opts);
3495
- return simulateAndWrite({
3781
+ return executeCalls({
3496
3782
  publicClient: this.publicClient,
3497
3783
  walletClient: this.walletClient,
3498
- address: this.proxy,
3499
- abi: mercuryAbis.bStaking,
3500
- functionName: "withdraw",
3501
- args: [bToken, amount],
3784
+ calls: [this.calls.staking.withdraw(bToken, amount)],
3502
3785
  account,
3503
3786
  confirmations: opts?.confirmations,
3504
3787
  onSimulateError: opts?.onSimulateError
3505
3788
  });
3506
3789
  }
3507
3790
  async claim(bToken, opts) {
3508
- const wallet = this.requireWallet();
3509
3791
  const account = this.getAccount(opts);
3510
3792
  const user = opts?.user ?? account;
3511
3793
  const asNative = opts?.asNative ?? false;
3794
+ const wallet = this.requireWallet();
3512
3795
  try {
3513
3796
  const { result, request } = await this.publicClient.simulateContract({
3514
3797
  address: this.proxy,
@@ -3517,7 +3800,10 @@ var BaselineSDK = class _BaselineSDK {
3517
3800
  args: [bToken, user, asNative],
3518
3801
  account
3519
3802
  });
3520
- const hash = await wallet.writeContract(request);
3803
+ const hash = await wallet.writeContract({
3804
+ ...request,
3805
+ account: resolveWriteAccount(wallet, account)
3806
+ });
3521
3807
  if (opts?.confirmations)
3522
3808
  await this.publicClient.waitForTransactionReceipt({
3523
3809
  hash,
@@ -3568,13 +3854,12 @@ var BaselineSDK = class _BaselineSDK {
3568
3854
  }
3569
3855
  async borrow(bToken, amount, recipient, opts) {
3570
3856
  const account = this.getAccount(opts);
3571
- const functionName = opts?.outputNative ? "borrowNative" : "borrow";
3572
3857
  return simulateAndWrite({
3573
3858
  publicClient: this.publicClient,
3574
3859
  walletClient: this.walletClient,
3575
3860
  address: this.proxy,
3576
3861
  abi: mercuryAbis.bCredit,
3577
- functionName,
3862
+ functionName: opts?.outputNative ? "borrowNative" : "borrow",
3578
3863
  args: [bToken, amount, recipient],
3579
3864
  account,
3580
3865
  confirmations: opts?.confirmations,
@@ -3582,20 +3867,18 @@ var BaselineSDK = class _BaselineSDK {
3582
3867
  });
3583
3868
  }
3584
3869
  async repay(bToken, reservesIn, recipient, opts) {
3585
- const useNative = shouldUseNative(opts?.useNative, this.config);
3586
3870
  const account = this.getAccount(opts);
3587
- const functionName = useNative ? "repayWithNative" : "repay";
3588
- const args = useNative ? [bToken, recipient] : [bToken, reservesIn, recipient];
3589
- const value = valueForNative(useNative, reservesIn);
3871
+ const call = this.calls.credit.repay(bToken, reservesIn, recipient, opts);
3872
+ const useNative = shouldUseNative(opts?.useNative, this.config);
3590
3873
  return simulateAndWrite({
3591
3874
  publicClient: this.publicClient,
3592
3875
  walletClient: this.walletClient,
3593
- address: this.proxy,
3876
+ address: call.to,
3594
3877
  abi: mercuryAbis.bCredit,
3595
- functionName,
3596
- args,
3878
+ functionName: useNative ? "repayWithNative" : "repay",
3879
+ args: useNative ? [bToken, recipient] : [bToken, reservesIn, recipient],
3597
3880
  account,
3598
- value,
3881
+ value: call.value,
3599
3882
  confirmations: opts?.confirmations,
3600
3883
  onSimulateError: opts?.onSimulateError
3601
3884
  });
@@ -3684,6 +3967,15 @@ var BaselineSDK = class _BaselineSDK {
3684
3967
  userAccumulator
3685
3968
  };
3686
3969
  }
3970
+ async getEarned(bToken, user) {
3971
+ const earned = await this.publicClient.readContract({
3972
+ address: this.proxy,
3973
+ abi: mercuryAbis.bStaking,
3974
+ functionName: "getEarned",
3975
+ args: [bToken, user]
3976
+ });
3977
+ return earned;
3978
+ }
3687
3979
  async getCreditAccount(bToken, user) {
3688
3980
  const [collateral, debt] = await this.publicClient.readContract({
3689
3981
  address: this.proxy,
@@ -3723,21 +4015,17 @@ var BaselineSDK = class _BaselineSDK {
3723
4015
  async ensureApproval(token, spender, required, opts) {
3724
4016
  const account = this.getAccount(opts);
3725
4017
  const policy = opts?.policy ?? this.config?.approvals ?? "infinite";
3726
- await ensureAllowance({
3727
- publicClient: this.publicClient,
3728
- walletClient: this.walletClient,
3729
- token,
4018
+ const calls = await this.calls.approval.ensure(token, spender, required, {
3730
4019
  owner: account,
3731
- spender,
3732
- required,
3733
- policy,
3734
- confirmations: opts?.confirmations
4020
+ policy
3735
4021
  });
4022
+ const [call] = calls;
4023
+ if (!call) return;
4024
+ const amount = policy === "infinite" ? 2n ** 256n - 1n : required;
4025
+ await this.approve(token, spender, amount, opts);
3736
4026
  }
3737
4027
  // ---------- Lens queries ----------
3738
4028
  async getBTokenInfo(bToken) {
3739
- const bytecode = await this.publicClient.getBytecode({ address: bToken });
3740
- const hasBytecode = !!bytecode && bytecode !== "0x";
3741
4029
  const results = await this.publicClient.multicall({
3742
4030
  allowFailure: true,
3743
4031
  contracts: [
@@ -3824,14 +4112,10 @@ var BaselineSDK = class _BaselineSDK {
3824
4112
  const reserveDecimals = normalizeQuoteState(
3825
4113
  result(12)
3826
4114
  )?.reserveDecimals;
3827
- const hasBaselineState = reserve !== void 0 && reserve.toLowerCase() !== ZERO_ADDRESS && maker !== void 0;
3828
- const status = !hasBytecode ? "not_deployed" : !hasBaselineState ? "contract_only" : maker.initialized ? "initialized" : "baseline_uninitialized";
3829
4115
  return {
3830
4116
  chainId: this.chainId,
3831
4117
  relay: this.proxy,
3832
4118
  bToken,
3833
- status,
3834
- bytecode: hasBytecode,
3835
4119
  name,
3836
4120
  symbol,
3837
4121
  decimals,
@@ -3847,6 +4131,15 @@ var BaselineSDK = class _BaselineSDK {
3847
4131
  maker
3848
4132
  };
3849
4133
  }
4134
+ async getBTokenStatus(bToken, info) {
4135
+ const bytecode = await this.publicClient.getCode({ address: bToken });
4136
+ const hasBytecode = !!bytecode && bytecode !== "0x";
4137
+ const tokenInfo = info ?? await this.getBTokenInfo(bToken);
4138
+ const hasBaselineState = tokenInfo.reserve !== void 0 && tokenInfo.reserve.toLowerCase() !== ZERO_ADDRESS && tokenInfo.maker !== void 0;
4139
+ const maker = tokenInfo.maker;
4140
+ const status = !hasBytecode ? "not_deployed" : !hasBaselineState ? "contract_only" : maker?.initialized ? "initialized" : "baseline_uninitialized";
4141
+ return { status, bytecode: hasBytecode };
4142
+ }
3850
4143
  async getReserve(bToken) {
3851
4144
  const reserve = await this.publicClient.readContract({
3852
4145
  address: this.proxy,
@@ -3908,16 +4201,29 @@ function normalizeQuoteState(value) {
3908
4201
  const reserveDecimals = Array.isArray(value) ? value[6] : value.reserveDecimals;
3909
4202
  return typeof reserveDecimals === "number" ? { reserveDecimals } : void 0;
3910
4203
  }
3911
- function serializeCalls(calls) {
3912
- return calls.map((call) => ({
3913
- to: call.to,
3914
- data: call.data,
3915
- value: viem.toHex(call.value ?? 0n)
3916
- }));
4204
+
4205
+ // src/utils/slippage.ts
4206
+ function maxInWithSlippage(amountIn, slippageBps) {
4207
+ if (slippageBps < 0) throw new Error("slippageBps must be >= 0");
4208
+ return amountIn * BigInt(1e4 + slippageBps) / 10000n;
3917
4209
  }
4210
+ function minOutWithSlippage(amountOut, slippageBps) {
4211
+ if (slippageBps < 0) throw new Error("slippageBps must be >= 0");
4212
+ const numerator = amountOut * 10000n;
4213
+ const denom = BigInt(1e4 + slippageBps);
4214
+ return numerator / denom;
4215
+ }
4216
+
4217
+ // index.ts
4218
+ var abis = mercuryAbis;
4219
+ var supportedChainIds2 = supportedChainIds;
3918
4220
 
3919
4221
  exports.BaselineSDK = BaselineSDK;
3920
4222
  exports.SDKError = SDKError;
3921
- exports.abis = mercuryAbis;
4223
+ exports.abis = abis;
4224
+ exports.calls = calls_exports;
4225
+ exports.maxInWithSlippage = maxInWithSlippage;
4226
+ exports.minOutWithSlippage = minOutWithSlippage;
3922
4227
  exports.serializeCalls = serializeCalls;
3923
- exports.supportedChainIds = supportedChainIds;
4228
+ exports.simulateCalls = simulateCalls;
4229
+ exports.supportedChainIds = supportedChainIds2;