@trustware/sdk-staging 1.1.10-staging.0 → 1.1.11-staging.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +54 -21
  2. package/dist/constants.cjs +1 -1
  3. package/dist/constants.mjs +1 -1
  4. package/dist/{core-BPLiD1UG.d.ts → core-B1WCJfDI.d.ts} +15 -2
  5. package/dist/{core-B7Ez-5-r.d.cts → core-CeNTuqPz.d.cts} +15 -2
  6. package/dist/core.cjs +365 -279
  7. package/dist/core.cjs.map +1 -1
  8. package/dist/core.d.cts +2 -2
  9. package/dist/core.d.ts +2 -2
  10. package/dist/core.mjs +363 -278
  11. package/dist/core.mjs.map +1 -1
  12. package/dist/index.cjs +375 -170
  13. package/dist/index.cjs.map +1 -1
  14. package/dist/index.d.cts +11 -5
  15. package/dist/index.d.ts +11 -5
  16. package/dist/index.mjs +373 -169
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/{manager-B6NNV-E_.d.ts → manager-Bw8b1wSD.d.ts} +136 -21
  19. package/dist/{manager-BwjyFjjz.d.cts → manager-DNGk1YkR.d.cts} +136 -21
  20. package/dist/{metadata-BiTMMvlY.d.ts → metadata-C__KMeuz.d.ts} +1 -1
  21. package/dist/{metadata-HCflXcsF.d.cts → metadata-Dk4R8_-T.d.cts} +1 -1
  22. package/dist/smart-account.cjs +49 -44
  23. package/dist/smart-account.cjs.map +1 -1
  24. package/dist/smart-account.d.cts +17 -12
  25. package/dist/smart-account.d.ts +17 -12
  26. package/dist/smart-account.mjs +49 -44
  27. package/dist/smart-account.mjs.map +1 -1
  28. package/dist/wallet.cjs +54 -39
  29. package/dist/wallet.cjs.map +1 -1
  30. package/dist/wallet.d.cts +3 -3
  31. package/dist/wallet.d.ts +3 -3
  32. package/dist/wallet.mjs +54 -39
  33. package/dist/wallet.mjs.map +1 -1
  34. package/dist/widget.cjs +369 -170
  35. package/dist/widget.cjs.map +1 -1
  36. package/dist/widget.mjs +369 -169
  37. package/dist/widget.mjs.map +1 -1
  38. package/package.json +73 -5
package/dist/core.mjs CHANGED
@@ -25,16 +25,14 @@ var init_defaults = __esm({
25
25
  });
26
26
 
27
27
  // src/types/config.ts
28
- var DEFAULT_RETRY_CONFIG, DEFAULT_FEATURE_FLAGS;
28
+ var DEFAULT_RETRY_CONFIG, RATE_LIMIT_WAIT_BUDGET_MS, DEFAULT_FEATURE_FLAGS;
29
29
  var init_config = __esm({
30
30
  "src/types/config.ts"() {
31
31
  "use strict";
32
32
  DEFAULT_RETRY_CONFIG = {
33
- autoRetry: true,
34
- maxRetries: 3,
35
- baseDelayMs: 1e3,
36
33
  approachingThreshold: 5
37
34
  };
35
+ RATE_LIMIT_WAIT_BUDGET_MS = 1e4;
38
36
  DEFAULT_FEATURE_FLAGS = {
39
37
  tokensPagination: true,
40
38
  balanceStreaming: false,
@@ -53,7 +51,7 @@ var init_constants = __esm({
53
51
  "src/constants.ts"() {
54
52
  "use strict";
55
53
  SDK_NAME = "@trustware/sdk";
56
- SDK_VERSION = "1.1.10-staging.0";
54
+ SDK_VERSION = "1.1.11-staging.2";
57
55
  API_ROOT = "https://bv-staging-api.trustware.io";
58
56
  API_PREFIX = "/api";
59
57
  WALLETCONNECT_PROJECT_ID = "72ea74c400f5111d43aea638d7d83a24";
@@ -135,50 +133,54 @@ function notifyRateLimitCallbacks(info, isRateLimited, retryCount) {
135
133
  retry.onRateLimitApproaching(info, retry.approachingThreshold);
136
134
  }
137
135
  }
138
- function calculateBackoffDelay(baseDelayMs, retryCount, retryAfter) {
139
- if (retryAfter && retryAfter > 0) {
140
- return retryAfter * 1e3;
136
+ function serverDirectedWaitMs(info) {
137
+ if (!info) return null;
138
+ if (typeof info.retryAfter === "number" && info.retryAfter > 0) {
139
+ return info.retryAfter * 1e3;
141
140
  }
142
- return baseDelayMs * Math.pow(2, retryCount);
141
+ if (typeof info.reset === "number" && info.reset > 0) {
142
+ const untilReset = info.reset * 1e3 - Date.now();
143
+ if (untilReset > 0) return untilReset;
144
+ }
145
+ return null;
143
146
  }
144
147
  function sleep(ms) {
145
148
  return new Promise((resolve) => setTimeout(resolve, ms));
146
149
  }
147
- async function rateLimitedFetch(url, options = {}) {
148
- const { skipRateLimit, ...fetchOptions } = options;
149
- const cfg = TrustwareConfigStore.get();
150
- if (!cfg.retry.autoRetry || skipRateLimit) {
151
- return fetch(url, fetchOptions);
152
- }
153
- const { maxRetries, baseDelayMs } = cfg.retry;
150
+ async function withRateLimitRetry(attempt) {
151
+ let waitedMs = 0;
154
152
  let retryCount = 0;
155
153
  while (true) {
156
- const response = await fetch(url, fetchOptions);
154
+ const response = await attempt();
157
155
  const rateLimitInfo = parseRateLimitHeaders(response);
158
- if (response.status === 429) {
156
+ if (response.status !== 429) {
159
157
  if (rateLimitInfo) {
160
- notifyRateLimitCallbacks(rateLimitInfo, true, retryCount);
161
- }
162
- if (retryCount >= maxRetries) {
163
- throw new RateLimitError(
164
- rateLimitInfo || { limit: 0, remaining: 0, reset: 0 },
165
- true
166
- );
158
+ notifyRateLimitCallbacks(rateLimitInfo, false, 0);
167
159
  }
168
- const delay = calculateBackoffDelay(
169
- baseDelayMs,
170
- retryCount,
171
- rateLimitInfo?.retryAfter
172
- );
173
- await sleep(delay);
174
- retryCount++;
175
- continue;
160
+ return response;
176
161
  }
177
162
  if (rateLimitInfo) {
178
- notifyRateLimitCallbacks(rateLimitInfo, false, 0);
163
+ notifyRateLimitCallbacks(rateLimitInfo, true, retryCount);
164
+ }
165
+ const waitMs = serverDirectedWaitMs(rateLimitInfo);
166
+ const info = rateLimitInfo || { limit: 0, remaining: 0, reset: 0 };
167
+ if (waitMs === null) {
168
+ throw new RateLimitError(info, true);
179
169
  }
180
- return response;
170
+ if (waitedMs + waitMs > RATE_LIMIT_WAIT_BUDGET_MS) {
171
+ throw new RateLimitError(info, false);
172
+ }
173
+ await sleep(waitMs);
174
+ waitedMs += waitMs;
175
+ retryCount++;
176
+ }
177
+ }
178
+ async function rateLimitedFetch(url, options = {}) {
179
+ const { skipRateLimit, ...fetchOptions } = options;
180
+ if (skipRateLimit) {
181
+ return fetch(url, fetchOptions);
181
182
  }
183
+ return withRateLimitRetry(() => fetch(url, fetchOptions));
182
184
  }
183
185
  var RateLimitError;
184
186
  var init_http = __esm({
@@ -186,9 +188,11 @@ var init_http = __esm({
186
188
  "use strict";
187
189
  init_constants();
188
190
  init_config2();
191
+ init_config();
189
192
  RateLimitError = class extends Error {
190
193
  constructor(info, retriesExhausted) {
191
- const message = retriesExhausted ? `Rate limit exceeded after max retries. Try again in ${info.retryAfter ?? Math.ceil((info.reset * 1e3 - Date.now()) / 1e3)} seconds.` : `Rate limit exceeded. Try again in ${info.retryAfter} seconds.`;
194
+ const seconds = info.retryAfter ?? (info.reset > 0 ? Math.max(0, Math.ceil((info.reset * 1e3 - Date.now()) / 1e3)) : null);
195
+ const message = seconds === null ? "Rate limit exceeded. The server did not say when to retry." : `Rate limit exceeded. Try again in ${seconds} seconds.`;
192
196
  super(message);
193
197
  this.name = "RateLimitError";
194
198
  this.rateLimitInfo = info;
@@ -1845,7 +1849,7 @@ async function getBalances(chainRef, address, opts) {
1845
1849
  if (cached) return cached;
1846
1850
  }
1847
1851
  const url = `${apiBase()}/v1/data/wallets/${encodeURIComponent(chainKey)}/${trimmedAddress}/balances`;
1848
- const response = await fetch(url, {
1852
+ const response = await rateLimitedFetch(url, {
1849
1853
  method: "GET",
1850
1854
  credentials: "omit",
1851
1855
  headers: jsonHeaders()
@@ -1984,6 +1988,20 @@ var init_eipWallets = __esm({
1984
1988
  "src/wallets/eipWallets.ts"() {
1985
1989
  "use strict";
1986
1990
  CHAIN_PARAMS = {
1991
+ 1: {
1992
+ chainIdHex: "0x1",
1993
+ chainName: "Ethereum",
1994
+ rpcUrls: ["https://eth.llamarpc.com"],
1995
+ nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
1996
+ blockExplorerUrls: ["https://etherscan.io"]
1997
+ },
1998
+ 137: {
1999
+ chainIdHex: "0x89",
2000
+ chainName: "Polygon",
2001
+ rpcUrls: ["https://polygon-rpc.com"],
2002
+ nativeCurrency: { name: "POL", symbol: "POL", decimals: 18 },
2003
+ blockExplorerUrls: ["https://polygonscan.com"]
2004
+ },
1987
2005
  8453: {
1988
2006
  chainIdHex: "0x2105",
1989
2007
  chainName: "Base",
@@ -4057,6 +4075,19 @@ async function submitReceipt(intentId, txHash, sponsorshipRequestId, eoaAddress)
4057
4075
  const j = await r.json();
4058
4076
  return j.data;
4059
4077
  }
4078
+ async function submitStepReceipt(intentId, stepIndex, txHash) {
4079
+ const r = await rateLimitedFetch(
4080
+ `${apiBase()}/v1/route-intent/${intentId}/steps/${stepIndex}/receipt`,
4081
+ {
4082
+ method: "POST",
4083
+ headers: jsonHeaders({ "Idempotency-Key": txHash }),
4084
+ body: JSON.stringify({ txHash })
4085
+ }
4086
+ );
4087
+ await assertOK(r);
4088
+ const j = await r.json();
4089
+ return j.data;
4090
+ }
4060
4091
  async function getStatus(intentId) {
4061
4092
  const r = await rateLimitedFetch(
4062
4093
  `${apiBase()}/v1/route-intent/${intentId}/status`,
@@ -4066,7 +4097,18 @@ async function getStatus(intentId) {
4066
4097
  );
4067
4098
  await assertOK(r);
4068
4099
  const j = await r.json();
4069
- return j.data;
4100
+ return normalizeStatusPayload(j.data);
4101
+ }
4102
+ function normalizeStatusPayload(raw) {
4103
+ if (!raw || typeof raw !== "object") return raw;
4104
+ const wire = raw;
4105
+ const out = { ...wire };
4106
+ for (const [snake, camel] of Object.entries(STATUS_WIRE_TO_CAMEL)) {
4107
+ if (out[camel] !== void 0) continue;
4108
+ if (!(snake in wire)) continue;
4109
+ out[camel] = wire[snake];
4110
+ }
4111
+ return out;
4070
4112
  }
4071
4113
  async function pollStatus(intentId, { intervalMs = 2e3, timeoutMs = 5 * 6e4 } = {}) {
4072
4114
  const t0 = Date.now();
@@ -4077,12 +4119,39 @@ async function pollStatus(intentId, { intervalMs = 2e3, timeoutMs = 5 * 6e4 } =
4077
4119
  await new Promise((r) => setTimeout(r, intervalMs));
4078
4120
  }
4079
4121
  }
4122
+ var STATUS_WIRE_TO_CAMEL;
4080
4123
  var init_routes = __esm({
4081
4124
  "src/core/routes.ts"() {
4082
4125
  "use strict";
4083
4126
  init_http();
4084
4127
  init_store();
4085
4128
  init_address();
4129
+ STATUS_WIRE_TO_CAMEL = {
4130
+ intent_id: "intentId",
4131
+ from_address: "fromAddress",
4132
+ to_address: "toAddress",
4133
+ from_chain_id: "fromChainId",
4134
+ to_chain_id: "toChainId",
4135
+ source_tx_hash: "sourceTxHash",
4136
+ dest_tx_hash: "destTxHash",
4137
+ request_id: "requestId",
4138
+ provider_request_id: "providerRequestId",
4139
+ transaction_request: "transactionRequest",
4140
+ status_raw: "statusRaw",
4141
+ route_path: "routePath",
4142
+ route_status: "routeStatus",
4143
+ to_amount_wei: "toAmountWei",
4144
+ from_chain_block: "fromChainBlock",
4145
+ to_chain_block: "toChainBlock",
4146
+ from_chain_tx_url: "fromChainTxUrl",
4147
+ to_chain_tx_url: "toChainTxUrl",
4148
+ gas_status: "gasStatus",
4149
+ is_gmp_transaction: "isGMPTransaction",
4150
+ axelar_transaction_url: "axelarTransactionUrl",
4151
+ create_date: "createdDate",
4152
+ update_date: "updatedDate",
4153
+ time_spent_ms: "timeSpentMs"
4154
+ };
4086
4155
  }
4087
4156
  });
4088
4157
 
@@ -6145,6 +6214,258 @@ var init_TrustwareError = __esm({
6145
6214
  }
6146
6215
  });
6147
6216
 
6217
+ // src/core/tx.ts
6218
+ import { keccak256, encodeFunctionData, parseAbi } from "viem";
6219
+ function backendChainId(chain, fallback) {
6220
+ const preferred = chain?.networkIdentifier ?? chain?.chainId ?? chain?.id;
6221
+ return String(preferred ?? fallback ?? "");
6222
+ }
6223
+ function sleep2(ms) {
6224
+ return new Promise((resolve) => setTimeout(resolve, ms));
6225
+ }
6226
+ async function sendEvmTx(w, tx) {
6227
+ if (w.type === "eip1193") {
6228
+ const from = await w.getAddress();
6229
+ const params = {
6230
+ from,
6231
+ to: tx.to,
6232
+ data: tx.data,
6233
+ value: tx.value ? `0x${tx.value.toString(16)}` : "0x0"
6234
+ };
6235
+ if (tx.chainId !== void 0) {
6236
+ params.chainId = `0x${tx.chainId.toString(16)}`;
6237
+ }
6238
+ const hash = await w.request({
6239
+ method: "eth_sendTransaction",
6240
+ params: [params]
6241
+ });
6242
+ return hash;
6243
+ }
6244
+ const response = await w.sendTransaction({
6245
+ to: tx.to,
6246
+ data: tx.data,
6247
+ value: tx.value,
6248
+ chainId: tx.chainId
6249
+ });
6250
+ return response.hash;
6251
+ }
6252
+ async function waitForTxConfirmation(chainId, txHash) {
6253
+ const timeoutMs = 12e4;
6254
+ const intervalMs = 2e3;
6255
+ const started = Date.now();
6256
+ while (Date.now() - started < timeoutMs) {
6257
+ const status = await getEVMTxStatus({ chainId, txHash });
6258
+ if (status.status === "success") return;
6259
+ if (status.status === "reverted") {
6260
+ throw new Error("Approval transaction reverted");
6261
+ }
6262
+ await sleep2(intervalMs);
6263
+ }
6264
+ throw new Error("Timed out waiting for approval confirmation");
6265
+ }
6266
+ function requiredApprovalAmount(planAmountWei, routeAmountWei) {
6267
+ if (planAmountWei >= UNLIMITED_APPROVAL_FLOOR && routeAmountWei !== void 0 && routeAmountWei > 0n) {
6268
+ return routeAmountWei;
6269
+ }
6270
+ return planAmountWei;
6271
+ }
6272
+ function approvalSatisfied(currentAllowance, requiredWei) {
6273
+ if (requiredWei === 0n) return currentAllowance === 0n;
6274
+ return currentAllowance >= requiredWei;
6275
+ }
6276
+ async function ensureApprovals(w, approvals, fallbackChainId, intentId, routeAmountWei) {
6277
+ if (!approvals || approvals.length === 0) return;
6278
+ const owner = await w.getAddress();
6279
+ for (const [stepIndex, approval] of approvals.entries()) {
6280
+ const spender = approval.spender;
6281
+ const tokenAddress = approval.tokenAddress;
6282
+ const amount = approval.amount;
6283
+ if (!spender || !tokenAddress || !amount) continue;
6284
+ const chainId = approval.chainId || String(fallbackChainId ?? "");
6285
+ if (!chainId) continue;
6286
+ const amountWei = requiredApprovalAmount(BigInt(amount), routeAmountWei);
6287
+ let currentAllowance = 0n;
6288
+ try {
6289
+ const { allowance } = await getEVMAllowance({
6290
+ chainId,
6291
+ tokenAddress,
6292
+ ownerAddress: owner,
6293
+ spenderAddress: spender
6294
+ });
6295
+ currentAllowance = BigInt(allowance || "0");
6296
+ } catch {
6297
+ }
6298
+ if (approvalSatisfied(currentAllowance, amountWei)) continue;
6299
+ const data = encodeFunctionData({
6300
+ abi: erc20ApproveAbi,
6301
+ functionName: "approve",
6302
+ args: [spender, amountWei]
6303
+ });
6304
+ const hash = await sendEvmTx(w, {
6305
+ to: tokenAddress,
6306
+ data,
6307
+ value: 0n,
6308
+ chainId: Number.isFinite(Number(chainId)) ? Number(chainId) : void 0
6309
+ });
6310
+ if (intentId) {
6311
+ void submitStepReceipt(intentId, stepIndex, hash).catch(() => {
6312
+ });
6313
+ }
6314
+ await waitForTxConfirmation(chainId, hash);
6315
+ }
6316
+ }
6317
+ function isUserRejected(e2) {
6318
+ const code = e2?.code ?? e2?.data?.code;
6319
+ if (code === 4001) return true;
6320
+ const msg = String(e2?.message || e2)?.toLowerCase?.() || "";
6321
+ return msg.includes("user rejected") || msg.includes("user denied");
6322
+ }
6323
+ async function sendRouteTransaction(b, fallbackChainId, options) {
6324
+ const w = walletManager.wallet;
6325
+ if (!w) throw new Error("Trustware.wallet not configured");
6326
+ const txReq = b.txReq;
6327
+ if (isEvmTxRequest(txReq)) {
6328
+ if (w.ecosystem !== "evm") {
6329
+ throw new Error("An EVM wallet is required for this route");
6330
+ }
6331
+ const to = txReq.to ?? txReq.target;
6332
+ const data = txReq.data;
6333
+ const value = txReq.value ? BigInt(txReq.value) : 0n;
6334
+ const target = Number(txReq.chainId ?? fallbackChainId);
6335
+ let validatedSponsorship;
6336
+ if (b.sponsorship) {
6337
+ if (keccak256(data) === b.sponsorship.callDataHash) {
6338
+ validatedSponsorship = b.sponsorship;
6339
+ }
6340
+ }
6341
+ if (Number.isFinite(target)) {
6342
+ const current = await w.getChainId();
6343
+ if (current !== target) {
6344
+ try {
6345
+ await w.switchChain(target);
6346
+ } catch {
6347
+ }
6348
+ }
6349
+ }
6350
+ if (!validatedSponsorship && !options?.approvalsEnsured) {
6351
+ await ensureApprovals(
6352
+ w,
6353
+ b.route?.execution?.approvals,
6354
+ Number.isFinite(target) ? target : void 0,
6355
+ b.intentId,
6356
+ BigInt(b.route?.estimate?.fromAmount ?? "0")
6357
+ );
6358
+ }
6359
+ if (w.type === "eip1193") {
6360
+ const from = await w.getAddress();
6361
+ const hexValue = value ? `0x${value.toString(16)}` : "0x0";
6362
+ const params = {
6363
+ from,
6364
+ to,
6365
+ data,
6366
+ value: hexValue
6367
+ };
6368
+ if (Number.isFinite(target)) {
6369
+ params.chainId = `0x${target.toString(16)}`;
6370
+ }
6371
+ const hash = await w.request({
6372
+ method: "eth_sendTransaction",
6373
+ params: [params]
6374
+ });
6375
+ return hash;
6376
+ }
6377
+ const response = await w.sendTransaction({
6378
+ to,
6379
+ data,
6380
+ value,
6381
+ chainId: Number.isFinite(target) ? target : void 0,
6382
+ ...validatedSponsorship ? {
6383
+ paymasterAndData: validatedSponsorship.paymasterAndData
6384
+ } : {}
6385
+ });
6386
+ return response.hash;
6387
+ }
6388
+ if (isSerializedSolanaTxRequest(txReq)) {
6389
+ if (w.ecosystem !== "solana") {
6390
+ throw new Error("A Solana wallet is required for this route");
6391
+ }
6392
+ const { getSharedRegistry: getSharedRegistry2 } = await Promise.resolve().then(() => (init_registryClient(), registryClient_exports));
6393
+ const registry = getSharedRegistry2();
6394
+ await registry.ensureChainsLoaded();
6395
+ const chain = registry.chain(
6396
+ String(fallbackChainId ?? txReq.chainId ?? "")
6397
+ );
6398
+ return w.sendSerializedTransaction(
6399
+ txReq.data,
6400
+ backendChainId(chain, fallbackChainId ?? txReq.chainId)
6401
+ );
6402
+ }
6403
+ throw new Error("Invalid route transaction payload");
6404
+ }
6405
+ async function runTopUp(params) {
6406
+ const w = walletManager.wallet;
6407
+ if (!w) throw new Error("Trustware.wallet not configured");
6408
+ const { getSharedRegistry: getSharedRegistry2 } = await Promise.resolve().then(() => (init_registryClient(), registryClient_exports));
6409
+ const reg = getSharedRegistry2();
6410
+ await reg.ensureLoaded();
6411
+ const fromAddress = await w.getAddress();
6412
+ const currentChainRef = w.ecosystem === "evm" ? String(await w.getChainId()) : await w.getChainKey?.() ?? "solana-mainnet-beta";
6413
+ const originalChain = w.ecosystem === "evm" ? await w.getChainId() : void 0;
6414
+ const fromChain = params.fromChain ?? currentChainRef;
6415
+ const { TrustwareConfigStore: TrustwareConfigStore2 } = await Promise.resolve().then(() => (init_store(), store_exports));
6416
+ const cfg = TrustwareConfigStore2.get();
6417
+ const toChain = params.toChain ?? String(cfg.routes.toChain);
6418
+ const fromToken = reg.resolveToken(
6419
+ fromChain,
6420
+ params.fromToken ?? cfg.routes.fromToken ?? void 0
6421
+ ) ?? params.fromToken;
6422
+ const toToken = reg.resolveToken(
6423
+ toChain,
6424
+ params.toToken ?? cfg.routes.toToken ?? void 0
6425
+ ) ?? params.toToken;
6426
+ if (!fromToken || !toToken) {
6427
+ throw new Error("Unable to resolve route tokens");
6428
+ }
6429
+ try {
6430
+ const build = await buildRoute({
6431
+ fromChain,
6432
+ toChain,
6433
+ fromToken,
6434
+ toToken,
6435
+ fromAmount: String(params.fromAmount),
6436
+ fromAddress,
6437
+ toAddress: params.toAddress ?? cfg.routes.toAddress ?? cfg.routes.fromAddress ?? fromAddress,
6438
+ slippage: cfg.routes.defaultSlippage
6439
+ });
6440
+ const hash = await sendRouteTransaction(build, fromChain);
6441
+ await submitReceipt(build.intentId, hash);
6442
+ return await pollStatus(build.intentId);
6443
+ } catch (e2) {
6444
+ if (isUserRejected(e2)) throw new Error("Transaction cancelled by user");
6445
+ throw e2;
6446
+ } finally {
6447
+ try {
6448
+ if (w.ecosystem === "evm" && originalChain && originalChain !== Number(fromChain)) {
6449
+ await w.switchChain(originalChain);
6450
+ }
6451
+ } catch {
6452
+ }
6453
+ }
6454
+ }
6455
+ var erc20ApproveAbi, UNLIMITED_APPROVAL_FLOOR;
6456
+ var init_tx = __esm({
6457
+ "src/core/tx.ts"() {
6458
+ "use strict";
6459
+ init_wallets();
6460
+ init_routes();
6461
+ init_sdkRpc();
6462
+ erc20ApproveAbi = parseAbi([
6463
+ "function approve(address spender, uint256 amount) returns (bool)"
6464
+ ]);
6465
+ UNLIMITED_APPROVAL_FLOOR = 1n << 255n;
6466
+ }
6467
+ });
6468
+
6148
6469
  // src/types/routes.ts
6149
6470
  var init_routes2 = __esm({
6150
6471
  "src/types/routes.ts"() {
@@ -6303,9 +6624,6 @@ function resolveConfig(input) {
6303
6624
  const theme = input.theme ?? "system";
6304
6625
  const messages = deepMerge(DEFAULT_MESSAGES, input.messages);
6305
6626
  const retry = {
6306
- autoRetry: input.retry?.autoRetry ?? DEFAULT_RETRY_CONFIG.autoRetry,
6307
- maxRetries: input.retry?.maxRetries ?? DEFAULT_RETRY_CONFIG.maxRetries,
6308
- baseDelayMs: input.retry?.baseDelayMs ?? DEFAULT_RETRY_CONFIG.baseDelayMs,
6309
6627
  approachingThreshold: input.retry?.approachingThreshold ?? DEFAULT_RETRY_CONFIG.approachingThreshold,
6310
6628
  onRateLimitInfo: input.retry?.onRateLimitInfo,
6311
6629
  onRateLimited: input.retry?.onRateLimited,
@@ -6430,242 +6748,6 @@ var init_store = __esm({
6430
6748
  }
6431
6749
  });
6432
6750
 
6433
- // src/core/tx.ts
6434
- import { keccak256, encodeFunctionData, parseAbi } from "viem";
6435
- function backendChainId(chain, fallback) {
6436
- const preferred = chain?.networkIdentifier ?? chain?.chainId ?? chain?.id;
6437
- return String(preferred ?? fallback ?? "");
6438
- }
6439
- function sleep2(ms) {
6440
- return new Promise((resolve) => setTimeout(resolve, ms));
6441
- }
6442
- async function sendEvmTx(w, tx) {
6443
- if (w.type === "eip1193") {
6444
- const from = await w.getAddress();
6445
- const params = {
6446
- from,
6447
- to: tx.to,
6448
- data: tx.data,
6449
- value: tx.value ? `0x${tx.value.toString(16)}` : "0x0"
6450
- };
6451
- if (tx.chainId !== void 0) {
6452
- params.chainId = `0x${tx.chainId.toString(16)}`;
6453
- }
6454
- const hash = await w.request({
6455
- method: "eth_sendTransaction",
6456
- params: [params]
6457
- });
6458
- return hash;
6459
- }
6460
- const response = await w.sendTransaction({
6461
- to: tx.to,
6462
- data: tx.data,
6463
- value: tx.value,
6464
- chainId: tx.chainId
6465
- });
6466
- return response.hash;
6467
- }
6468
- async function waitForTxConfirmation(chainId, txHash) {
6469
- const timeoutMs = 12e4;
6470
- const intervalMs = 2e3;
6471
- const started = Date.now();
6472
- while (Date.now() - started < timeoutMs) {
6473
- const status = await getEVMTxStatus({ chainId, txHash });
6474
- if (status.status === "success") return;
6475
- if (status.status === "reverted") {
6476
- throw new Error("Approval transaction reverted");
6477
- }
6478
- await sleep2(intervalMs);
6479
- }
6480
- throw new Error("Timed out waiting for approval confirmation");
6481
- }
6482
- async function ensureApprovals(w, approvals, fallbackChainId) {
6483
- if (!approvals || approvals.length === 0) return;
6484
- const owner = await w.getAddress();
6485
- for (const approval of approvals) {
6486
- const spender = approval.spender;
6487
- const tokenAddress = approval.tokenAddress;
6488
- const amount = approval.amount;
6489
- if (!spender || !tokenAddress || !amount) continue;
6490
- const chainId = approval.chainId || String(fallbackChainId ?? "");
6491
- if (!chainId) continue;
6492
- const amountWei = BigInt(amount);
6493
- if (amountWei === 0n) continue;
6494
- let currentAllowance = 0n;
6495
- try {
6496
- const { allowance } = await getEVMAllowance({
6497
- chainId,
6498
- tokenAddress,
6499
- ownerAddress: owner,
6500
- spenderAddress: spender
6501
- });
6502
- currentAllowance = BigInt(allowance || "0");
6503
- } catch {
6504
- }
6505
- if (currentAllowance >= amountWei) continue;
6506
- const data = encodeFunctionData({
6507
- abi: erc20ApproveAbi,
6508
- functionName: "approve",
6509
- args: [spender, amountWei]
6510
- });
6511
- const hash = await sendEvmTx(w, {
6512
- to: tokenAddress,
6513
- data,
6514
- value: 0n,
6515
- chainId: Number.isFinite(Number(chainId)) ? Number(chainId) : void 0
6516
- });
6517
- await waitForTxConfirmation(chainId, hash);
6518
- }
6519
- }
6520
- function isUserRejected(e2) {
6521
- const code = e2?.code ?? e2?.data?.code;
6522
- if (code === 4001) return true;
6523
- const msg = String(e2?.message || e2)?.toLowerCase?.() || "";
6524
- return msg.includes("user rejected") || msg.includes("user denied");
6525
- }
6526
- async function sendRouteTransaction(b, fallbackChainId) {
6527
- const w = walletManager.wallet;
6528
- if (!w) throw new Error("Trustware.wallet not configured");
6529
- const txReq = b.txReq;
6530
- if (isEvmTxRequest(txReq)) {
6531
- if (w.ecosystem !== "evm") {
6532
- throw new Error("An EVM wallet is required for this route");
6533
- }
6534
- const to = txReq.to ?? txReq.target;
6535
- const data = txReq.data;
6536
- const value = txReq.value ? BigInt(txReq.value) : 0n;
6537
- const target = Number(txReq.chainId ?? fallbackChainId);
6538
- let validatedSponsorship;
6539
- if (b.sponsorship) {
6540
- if (keccak256(data) === b.sponsorship.callDataHash) {
6541
- validatedSponsorship = b.sponsorship;
6542
- }
6543
- }
6544
- if (Number.isFinite(target)) {
6545
- const current = await w.getChainId();
6546
- if (current !== target) {
6547
- try {
6548
- await w.switchChain(target);
6549
- } catch {
6550
- }
6551
- }
6552
- }
6553
- if (!validatedSponsorship) {
6554
- await ensureApprovals(
6555
- w,
6556
- b.route?.execution?.approvals,
6557
- Number.isFinite(target) ? target : void 0
6558
- );
6559
- }
6560
- if (w.type === "eip1193") {
6561
- const from = await w.getAddress();
6562
- const hexValue = value ? `0x${value.toString(16)}` : "0x0";
6563
- const params = {
6564
- from,
6565
- to,
6566
- data,
6567
- value: hexValue
6568
- };
6569
- if (Number.isFinite(target)) {
6570
- params.chainId = `0x${target.toString(16)}`;
6571
- }
6572
- const hash = await w.request({
6573
- method: "eth_sendTransaction",
6574
- params: [params]
6575
- });
6576
- return hash;
6577
- }
6578
- const response = await w.sendTransaction({
6579
- to,
6580
- data,
6581
- value,
6582
- chainId: Number.isFinite(target) ? target : void 0,
6583
- ...validatedSponsorship ? {
6584
- paymasterAndData: validatedSponsorship.paymasterAndData
6585
- } : {}
6586
- });
6587
- return response.hash;
6588
- }
6589
- if (isSerializedSolanaTxRequest(txReq)) {
6590
- if (w.ecosystem !== "solana") {
6591
- throw new Error("A Solana wallet is required for this route");
6592
- }
6593
- const { getSharedRegistry: getSharedRegistry2 } = await Promise.resolve().then(() => (init_registryClient(), registryClient_exports));
6594
- const registry = getSharedRegistry2();
6595
- await registry.ensureChainsLoaded();
6596
- const chain = registry.chain(
6597
- String(fallbackChainId ?? txReq.chainId ?? "")
6598
- );
6599
- return w.sendSerializedTransaction(
6600
- txReq.data,
6601
- backendChainId(chain, fallbackChainId ?? txReq.chainId)
6602
- );
6603
- }
6604
- throw new Error("Invalid route transaction payload");
6605
- }
6606
- async function runTopUp(params) {
6607
- const w = walletManager.wallet;
6608
- if (!w) throw new Error("Trustware.wallet not configured");
6609
- const { getSharedRegistry: getSharedRegistry2 } = await Promise.resolve().then(() => (init_registryClient(), registryClient_exports));
6610
- const reg = getSharedRegistry2();
6611
- await reg.ensureLoaded();
6612
- const fromAddress = await w.getAddress();
6613
- const currentChainRef = w.ecosystem === "evm" ? String(await w.getChainId()) : await w.getChainKey?.() ?? "solana-mainnet-beta";
6614
- const originalChain = w.ecosystem === "evm" ? await w.getChainId() : void 0;
6615
- const fromChain = params.fromChain ?? currentChainRef;
6616
- const { TrustwareConfigStore: TrustwareConfigStore2 } = await Promise.resolve().then(() => (init_store(), store_exports));
6617
- const cfg = TrustwareConfigStore2.get();
6618
- const toChain = params.toChain ?? String(cfg.routes.toChain);
6619
- const fromToken = reg.resolveToken(
6620
- fromChain,
6621
- params.fromToken ?? cfg.routes.fromToken ?? void 0
6622
- ) ?? params.fromToken;
6623
- const toToken = reg.resolveToken(
6624
- toChain,
6625
- params.toToken ?? cfg.routes.toToken ?? void 0
6626
- ) ?? params.toToken;
6627
- if (!fromToken || !toToken) {
6628
- throw new Error("Unable to resolve route tokens");
6629
- }
6630
- try {
6631
- const build = await buildRoute({
6632
- fromChain,
6633
- toChain,
6634
- fromToken,
6635
- toToken,
6636
- fromAmount: String(params.fromAmount),
6637
- fromAddress,
6638
- toAddress: params.toAddress ?? cfg.routes.toAddress ?? cfg.routes.fromAddress ?? fromAddress,
6639
- slippage: cfg.routes.defaultSlippage
6640
- });
6641
- const hash = await sendRouteTransaction(build, fromChain);
6642
- await submitReceipt(build.intentId, hash);
6643
- return await pollStatus(build.intentId);
6644
- } catch (e2) {
6645
- if (isUserRejected(e2)) throw new Error("Transaction cancelled by user");
6646
- throw e2;
6647
- } finally {
6648
- try {
6649
- if (w.ecosystem === "evm" && originalChain && originalChain !== Number(fromChain)) {
6650
- await w.switchChain(originalChain);
6651
- }
6652
- } catch {
6653
- }
6654
- }
6655
- }
6656
- var erc20ApproveAbi;
6657
- var init_tx = __esm({
6658
- "src/core/tx.ts"() {
6659
- "use strict";
6660
- init_wallets();
6661
- init_routes();
6662
- init_sdkRpc();
6663
- erc20ApproveAbi = parseAbi([
6664
- "function approve(address spender, uint256 amount) returns (bool)"
6665
- ]);
6666
- }
6667
- });
6668
-
6669
6751
  // src/core/index.ts
6670
6752
  var _lastValidatedKey, Trustware;
6671
6753
  var init_core = __esm({
@@ -6674,6 +6756,7 @@ var init_core = __esm({
6674
6756
  init_store();
6675
6757
  init_wallets();
6676
6758
  init_routes();
6759
+ init_routes();
6677
6760
  init_balances();
6678
6761
  init_tx();
6679
6762
  init_http();
@@ -6808,6 +6891,7 @@ var init_core = __esm({
6808
6891
  buildRoute,
6809
6892
  buildDepositAddress,
6810
6893
  submitReceipt,
6894
+ submitStepReceipt,
6811
6895
  getStatus,
6812
6896
  pollStatus,
6813
6897
  getBalances,
@@ -6832,6 +6916,7 @@ var init_core2 = __esm({
6832
6916
  });
6833
6917
  init_core2();
6834
6918
  export {
6835
- Trustware
6919
+ Trustware,
6920
+ assertValidPostHook
6836
6921
  };
6837
6922
  //# sourceMappingURL=core.mjs.map