@riftresearch/sdk 0.10.0 → 0.11.1
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.d.ts +5 -11
- package/dist/index.js +145 -135
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -57,7 +57,6 @@ interface CalculatedInputAmount {
|
|
|
57
57
|
/** Maximum input required after slippage (optional - not all routes provide this) */
|
|
58
58
|
maximum?: U256;
|
|
59
59
|
}
|
|
60
|
-
type QuoteQuality = "fast" | "optimal";
|
|
61
60
|
/**
|
|
62
61
|
* A single fee component with amount in native currency and USD equivalent.
|
|
63
62
|
*/
|
|
@@ -175,6 +174,8 @@ interface EvmCallStep {
|
|
|
175
174
|
spenderAddress?: string;
|
|
176
175
|
/** Amount for display/verification (for approval, transfer_evm) */
|
|
177
176
|
amount?: U256;
|
|
177
|
+
/** DEX execution venue label (for dex_swap, e.g. "spandex.paraswap") */
|
|
178
|
+
venue?: string;
|
|
178
179
|
}
|
|
179
180
|
/**
|
|
180
181
|
* BTC Transfer step - send Bitcoin to an address.
|
|
@@ -296,8 +297,6 @@ interface QuoteParameters {
|
|
|
296
297
|
* `minimum`/`maximum` bounds; direct OTC routes may ignore it.
|
|
297
298
|
*/
|
|
298
299
|
slippageBps: number;
|
|
299
|
-
/** Optional DEX quote quality target for DEX-backed routes. */
|
|
300
|
-
quoteQuality?: QuoteQuality;
|
|
301
300
|
/**
|
|
302
301
|
* Approval amount strategy for ERC20 swaps.
|
|
303
302
|
* - "full" (default): approve max uint256
|
|
@@ -402,12 +401,6 @@ interface RiftSdkOptions {
|
|
|
402
401
|
apiUrl?: string;
|
|
403
402
|
/** Enable verbose debug logging for swap execution */
|
|
404
403
|
debug?: boolean;
|
|
405
|
-
/**
|
|
406
|
-
* Controls how EVM transactions are broadcast:
|
|
407
|
-
* - "sdk" (default): wallet signs via `walletClient.signTransaction`, SDK simulates and broadcasts
|
|
408
|
-
* - "wallet": wallet signs + broadcasts via `walletClient.sendTransaction`
|
|
409
|
-
*/
|
|
410
|
-
evmBroadcastMode?: "wallet" | "sdk";
|
|
411
404
|
/** Optional preflight checks before executing swaps */
|
|
412
405
|
preflight?: {
|
|
413
406
|
/** Check sender balance before executing EVM steps (default: true) */
|
|
@@ -421,7 +414,6 @@ declare class RiftSdk {
|
|
|
421
414
|
private preflightCheckBalances;
|
|
422
415
|
private integratorName;
|
|
423
416
|
private debug;
|
|
424
|
-
private evmBroadcastMode;
|
|
425
417
|
constructor(options: RiftSdkOptions);
|
|
426
418
|
private logDebug;
|
|
427
419
|
private unwrapEdenResult;
|
|
@@ -462,6 +454,8 @@ declare class RiftSdk {
|
|
|
462
454
|
private executeBtcTransferStep;
|
|
463
455
|
private buildQuoteResult;
|
|
464
456
|
private buildSwapResult;
|
|
457
|
+
private buildDexSwapRevertMessage;
|
|
458
|
+
private resolveDexVenueLabel;
|
|
465
459
|
private assertSufficientBalance;
|
|
466
460
|
private getAddress;
|
|
467
461
|
private getRefundAddress;
|
|
@@ -476,4 +470,4 @@ declare class RiftSdk {
|
|
|
476
470
|
getSwapStatus(swapId: string): Promise<SwapStatusResponse>;
|
|
477
471
|
}
|
|
478
472
|
declare function createRiftSdk(options: RiftSdkOptions): RiftSdk;
|
|
479
|
-
export { getSupportedModes, detectRoute, createRiftSdk, createCurrency, TokenIdentifier, SwapStatus, SwapRouterApiError, SwapRoute, SwapResult, SwapResponse, SupportedModes, SendBitcoinFn, RiftSwap, RiftSdkOptions, RiftSdk, QuoteResult,
|
|
473
|
+
export { getSupportedModes, detectRoute, createRiftSdk, createCurrency, TokenIdentifier, SwapStatus, SwapRouterApiError, SwapRoute, SwapResult, SwapResponse, SupportedModes, SendBitcoinFn, RiftSwap, RiftSdkOptions, RiftSdk, QuoteResult, QuoteParameters, NativeToken, GetQuoteResult, ExecutionStep, ExecutionAction, ExecuteSwapStepType, ExecuteSwapOptions, ExecuteSwapOnExecuteStepCallback, EvmChain, EvmCallStep, EvmCallKind, Erc20Token, Currency, Currencies, Chain, BtcTransferStep, BtcTransferKind, BitcoinChain };
|
package/dist/index.js
CHANGED
|
@@ -156,50 +156,108 @@ function getSupportedModes(from, to) {
|
|
|
156
156
|
import { erc20Abi } from "viem";
|
|
157
157
|
|
|
158
158
|
// src/client.ts
|
|
159
|
-
|
|
159
|
+
async function request(baseUrl, path, init) {
|
|
160
|
+
try {
|
|
161
|
+
const response = await fetch(`${baseUrl}${path}`, init);
|
|
162
|
+
const status = response.status;
|
|
163
|
+
const contentType = response.headers.get("content-type") ?? "";
|
|
164
|
+
let value = null;
|
|
165
|
+
if (status !== 204) {
|
|
166
|
+
if (contentType.includes("application/json")) {
|
|
167
|
+
try {
|
|
168
|
+
value = await response.json();
|
|
169
|
+
} catch {
|
|
170
|
+
value = null;
|
|
171
|
+
}
|
|
172
|
+
} else {
|
|
173
|
+
const text = await response.text();
|
|
174
|
+
value = text.length > 0 ? text : null;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
if (response.ok) {
|
|
178
|
+
return {
|
|
179
|
+
data: value,
|
|
180
|
+
error: null,
|
|
181
|
+
status
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
const message = value && typeof value === "object" && "error" in value && typeof value.error === "string" ? value.error : typeof value === "string" && value.length > 0 ? value : `Request failed with status ${status}`;
|
|
185
|
+
return {
|
|
186
|
+
data: null,
|
|
187
|
+
error: {
|
|
188
|
+
status,
|
|
189
|
+
value,
|
|
190
|
+
message
|
|
191
|
+
},
|
|
192
|
+
status
|
|
193
|
+
};
|
|
194
|
+
} catch (error) {
|
|
195
|
+
return {
|
|
196
|
+
data: null,
|
|
197
|
+
error: {
|
|
198
|
+
status: 0,
|
|
199
|
+
message: error instanceof Error ? error.message : String(error)
|
|
200
|
+
},
|
|
201
|
+
status: 0
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
function get(baseUrl, path) {
|
|
206
|
+
return request(baseUrl, path, {
|
|
207
|
+
method: "GET",
|
|
208
|
+
headers: {
|
|
209
|
+
accept: "application/json"
|
|
210
|
+
}
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
function postJson(baseUrl, path, body) {
|
|
214
|
+
return request(baseUrl, path, {
|
|
215
|
+
method: "POST",
|
|
216
|
+
headers: {
|
|
217
|
+
accept: "application/json",
|
|
218
|
+
"content-type": "application/json"
|
|
219
|
+
},
|
|
220
|
+
body: JSON.stringify(body)
|
|
221
|
+
});
|
|
222
|
+
}
|
|
160
223
|
function createClient(baseUrl) {
|
|
161
|
-
|
|
224
|
+
const normalizedBaseUrl = baseUrl.replace(/\/$/, "");
|
|
225
|
+
const swap = (params) => {
|
|
226
|
+
const swapId = encodeURIComponent(params.swapId);
|
|
227
|
+
return {
|
|
228
|
+
get: () => get(normalizedBaseUrl, `/swap/${swapId}`),
|
|
229
|
+
tx: {
|
|
230
|
+
post: (body) => postJson(normalizedBaseUrl, `/swap/${swapId}/tx`, body)
|
|
231
|
+
},
|
|
232
|
+
"refresh-step": {
|
|
233
|
+
post: (body) => postJson(normalizedBaseUrl, `/swap/${swapId}/refresh-step`, body)
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
};
|
|
237
|
+
swap.post = (body) => postJson(normalizedBaseUrl, "/swap", body);
|
|
238
|
+
return {
|
|
239
|
+
quote: {
|
|
240
|
+
post: (body) => postJson(normalizedBaseUrl, "/quote", body)
|
|
241
|
+
},
|
|
242
|
+
swap
|
|
243
|
+
};
|
|
162
244
|
}
|
|
163
245
|
|
|
164
246
|
// src/sdk.ts
|
|
165
247
|
var GAS_LIMIT_MULTIPLIER_NUMERATOR = 3n;
|
|
166
248
|
var GAS_LIMIT_MULTIPLIER_DENOMINATOR = 2n;
|
|
167
|
-
var FLASHBOTS_PROTECT_RPC_URL = "https://rpc.flashbots.net";
|
|
168
|
-
async function sendFlashbotsRawTransaction(serializedTransaction) {
|
|
169
|
-
const response = await fetch(FLASHBOTS_PROTECT_RPC_URL, {
|
|
170
|
-
method: "POST",
|
|
171
|
-
headers: { "content-type": "application/json" },
|
|
172
|
-
body: JSON.stringify({
|
|
173
|
-
jsonrpc: "2.0",
|
|
174
|
-
id: 1,
|
|
175
|
-
method: "eth_sendRawTransaction",
|
|
176
|
-
params: [serializedTransaction]
|
|
177
|
-
})
|
|
178
|
-
});
|
|
179
|
-
const json = await response.json().catch(() => null);
|
|
180
|
-
const errorMessage = typeof json?.error?.message === "string" ? json.error.message : undefined;
|
|
181
|
-
if (!response.ok || errorMessage) {
|
|
182
|
-
throw new Error(`Flashbots submission failed: ${errorMessage ?? `HTTP ${response.status}`}`);
|
|
183
|
-
}
|
|
184
|
-
if (!json || typeof json.result !== "string") {
|
|
185
|
-
throw new Error("Flashbots submission failed: invalid response");
|
|
186
|
-
}
|
|
187
|
-
return json.result;
|
|
188
|
-
}
|
|
189
249
|
|
|
190
250
|
class RiftSdk {
|
|
191
251
|
riftClient;
|
|
192
252
|
preflightCheckBalances;
|
|
193
253
|
integratorName;
|
|
194
254
|
debug;
|
|
195
|
-
evmBroadcastMode;
|
|
196
255
|
constructor(options) {
|
|
197
256
|
const baseUrl = (options.apiUrl ?? "https://api.rift.trade").replace(/\/$/, "");
|
|
198
257
|
this.riftClient = createClient(baseUrl);
|
|
199
258
|
this.preflightCheckBalances = options.preflight?.checkBalances !== false;
|
|
200
259
|
this.integratorName = options.integratorName;
|
|
201
260
|
this.debug = options.debug ?? false;
|
|
202
|
-
this.evmBroadcastMode = options.evmBroadcastMode ?? "sdk";
|
|
203
261
|
}
|
|
204
262
|
logDebug(message, data) {
|
|
205
263
|
if (!this.debug)
|
|
@@ -242,8 +300,7 @@ class RiftSdk {
|
|
|
242
300
|
from: params.from,
|
|
243
301
|
to: params.to,
|
|
244
302
|
amount: params.amount,
|
|
245
|
-
slippageBps: params.slippageBps
|
|
246
|
-
quoteQuality: params.quoteQuality
|
|
303
|
+
slippageBps: params.slippageBps
|
|
247
304
|
};
|
|
248
305
|
const riftQuote = this.unwrapEdenResult(await this.riftClient.quote.post(quoteRequest));
|
|
249
306
|
const quote = this.buildQuoteResult(riftQuote, params);
|
|
@@ -292,7 +349,7 @@ class RiftSdk {
|
|
|
292
349
|
kind: "kind" in step ? step.kind : undefined,
|
|
293
350
|
chainId: "chainId" in step ? step.chainId : undefined
|
|
294
351
|
});
|
|
295
|
-
const result = await this.executeStep(step, context, swapResponse.swapId);
|
|
352
|
+
const result = await this.executeStep(step, context, swapResponse.swapId, route);
|
|
296
353
|
this.logDebug("step completed", {
|
|
297
354
|
stepId: step.id,
|
|
298
355
|
txHash: result.txHash
|
|
@@ -324,15 +381,15 @@ class RiftSdk {
|
|
|
324
381
|
}
|
|
325
382
|
};
|
|
326
383
|
}
|
|
327
|
-
async executeStep(step, context, swapId) {
|
|
384
|
+
async executeStep(step, context, swapId, route) {
|
|
328
385
|
switch (step.action) {
|
|
329
386
|
case "evm_call":
|
|
330
|
-
return this.executeEvmCallStep(step, context, swapId);
|
|
387
|
+
return this.executeEvmCallStep(step, context, swapId, route);
|
|
331
388
|
case "btc_transfer":
|
|
332
389
|
return this.executeBtcTransferStep(step, context);
|
|
333
390
|
}
|
|
334
391
|
}
|
|
335
|
-
async executeEvmCallStep(step, context, swapId) {
|
|
392
|
+
async executeEvmCallStep(step, context, swapId, route) {
|
|
336
393
|
const walletClient = this.requireWalletClient(context);
|
|
337
394
|
const publicClient = this.requirePublicClient(context);
|
|
338
395
|
const account = walletClient.account;
|
|
@@ -351,32 +408,26 @@ class RiftSdk {
|
|
|
351
408
|
}
|
|
352
409
|
}
|
|
353
410
|
let effectiveStep = step;
|
|
354
|
-
let
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
411
|
+
let txRequest = {
|
|
412
|
+
account,
|
|
413
|
+
to: effectiveStep.to,
|
|
414
|
+
data: effectiveStep.calldata,
|
|
415
|
+
value: effectiveStep.value ? BigInt(effectiveStep.value) : undefined
|
|
416
|
+
};
|
|
417
|
+
let estimatedGas;
|
|
418
|
+
try {
|
|
419
|
+
estimatedGas = await publicClient.estimateGas(txRequest);
|
|
420
|
+
} catch (estimateError) {
|
|
421
|
+
if (effectiveStep.kind !== "dex_swap") {
|
|
422
|
+
throw estimateError;
|
|
423
|
+
}
|
|
424
|
+
this.logDebug("estimateGas failed; attempting refresh-step", {
|
|
425
|
+
swapId,
|
|
426
|
+
stepId: effectiveStep.id,
|
|
427
|
+
error: estimateError instanceof Error ? estimateError.message : String(estimateError)
|
|
428
|
+
});
|
|
363
429
|
try {
|
|
364
|
-
|
|
365
|
-
} catch (estimateError) {
|
|
366
|
-
if (effectiveStep.kind !== "dex_swap") {
|
|
367
|
-
throw estimateError;
|
|
368
|
-
}
|
|
369
|
-
this.logDebug("estimateGas failed; attempting refresh-step", {
|
|
370
|
-
swapId,
|
|
371
|
-
stepId: effectiveStep.id,
|
|
372
|
-
error: estimateError instanceof Error ? estimateError.message : String(estimateError)
|
|
373
|
-
});
|
|
374
|
-
let refreshed;
|
|
375
|
-
try {
|
|
376
|
-
refreshed = this.unwrapEdenResult(await this.riftClient.swap({ swapId })["refresh-step"].post({ stepId: effectiveStep.id }));
|
|
377
|
-
} catch (refreshError) {
|
|
378
|
-
throw new Error(`estimateGas failed for dex_swap step and refresh-step failed: ${refreshError instanceof Error ? refreshError.message : String(refreshError)}`);
|
|
379
|
-
}
|
|
430
|
+
const refreshed = this.unwrapEdenResult(await this.riftClient.swap({ swapId })["refresh-step"].post({ stepId: effectiveStep.id }));
|
|
380
431
|
if (!refreshed?.step) {
|
|
381
432
|
throw new Error("estimateGas failed for dex_swap step and refresh-step returned no step");
|
|
382
433
|
}
|
|
@@ -391,88 +442,36 @@ class RiftSdk {
|
|
|
391
442
|
value: effectiveStep.value ? BigInt(effectiveStep.value) : undefined
|
|
392
443
|
};
|
|
393
444
|
estimatedGas = await publicClient.estimateGas(txRequest);
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
gasLimit: gasLimit.toString()
|
|
400
|
-
});
|
|
401
|
-
if (this.evmBroadcastMode === "wallet") {
|
|
402
|
-
await context.onExecuteStep?.(effectiveStep.kind === "approval" ? "approval" : "transaction");
|
|
403
|
-
const txHash2 = await walletClient.sendTransaction({
|
|
404
|
-
...txRequest,
|
|
405
|
-
gas: gasLimit
|
|
406
|
-
});
|
|
407
|
-
const receipt2 = await publicClient.waitForTransactionReceipt({
|
|
408
|
-
hash: txHash2
|
|
409
|
-
});
|
|
410
|
-
if (receipt2.status !== "success") {
|
|
411
|
-
throw new Error(`EVM step transaction reverted (${effectiveStep.kind}) with hash ${txHash2}`);
|
|
412
|
-
}
|
|
413
|
-
return { txHash: txHash2 };
|
|
414
|
-
}
|
|
415
|
-
const nonce = await publicClient.getTransactionCount({
|
|
416
|
-
address: account.address,
|
|
417
|
-
blockTag: "pending"
|
|
418
|
-
});
|
|
419
|
-
const feeEstimate = await publicClient.estimateFeesPerGas().catch(() => {
|
|
420
|
-
return;
|
|
421
|
-
});
|
|
422
|
-
const feeParams = {};
|
|
423
|
-
if (feeEstimate?.maxFeePerGas !== undefined && feeEstimate?.maxPriorityFeePerGas !== undefined) {
|
|
424
|
-
feeParams.maxFeePerGas = feeEstimate.maxFeePerGas;
|
|
425
|
-
feeParams.maxPriorityFeePerGas = feeEstimate.maxPriorityFeePerGas;
|
|
426
|
-
} else if (feeEstimate?.gasPrice !== undefined) {
|
|
427
|
-
feeParams.gasPrice = feeEstimate.gasPrice;
|
|
428
|
-
}
|
|
429
|
-
const txToSign = {
|
|
430
|
-
...txRequest,
|
|
431
|
-
gas: gasLimit,
|
|
432
|
-
nonce,
|
|
433
|
-
...feeParams
|
|
434
|
-
};
|
|
435
|
-
await context.onExecuteStep?.(effectiveStep.kind === "approval" ? "approval" : "transaction");
|
|
436
|
-
const serializedTransaction = await walletClient.signTransaction(txToSign);
|
|
437
|
-
try {
|
|
438
|
-
const { nonce: _nonce, ...callRequest } = txToSign;
|
|
439
|
-
await publicClient.call({
|
|
440
|
-
...callRequest,
|
|
441
|
-
blockTag: "pending"
|
|
442
|
-
});
|
|
443
|
-
} catch (callError) {
|
|
444
|
-
if (effectiveStep.kind === "dex_swap" && !refreshedForFinalSimulation) {
|
|
445
|
-
refreshedForFinalSimulation = true;
|
|
446
|
-
this.logDebug("final simulation failed for dex_swap; attempting refresh-step before broadcast", {
|
|
447
|
-
swapId,
|
|
448
|
-
stepId: effectiveStep.id,
|
|
449
|
-
error: callError instanceof Error ? callError.message : String(callError)
|
|
450
|
-
});
|
|
451
|
-
const refreshed = this.unwrapEdenResult(await this.riftClient.swap({ swapId })["refresh-step"].post({ stepId: effectiveStep.id }));
|
|
452
|
-
if (!refreshed?.step || refreshed.step.kind !== "dex_swap") {
|
|
453
|
-
throw new Error("refresh-step returned invalid step");
|
|
454
|
-
}
|
|
455
|
-
effectiveStep = refreshed.step;
|
|
456
|
-
continue;
|
|
457
|
-
}
|
|
458
|
-
throw callError;
|
|
459
|
-
}
|
|
460
|
-
let txHash;
|
|
461
|
-
if (effectiveStep.kind === "dex_swap" && effectiveStep.chainId === 1) {
|
|
462
|
-
txHash = await sendFlashbotsRawTransaction(serializedTransaction);
|
|
463
|
-
} else {
|
|
464
|
-
txHash = await publicClient.sendRawTransaction({
|
|
465
|
-
serializedTransaction
|
|
445
|
+
} catch (retrySimulationError) {
|
|
446
|
+
this.logDebug("dex_swap simulation failed after refresh-step attempt", {
|
|
447
|
+
swapId,
|
|
448
|
+
stepId: effectiveStep.id,
|
|
449
|
+
error: retrySimulationError instanceof Error ? retrySimulationError.message : String(retrySimulationError)
|
|
466
450
|
});
|
|
451
|
+
throw new Error(this.buildDexSwapRevertMessage(route, effectiveStep.venue));
|
|
467
452
|
}
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
453
|
+
}
|
|
454
|
+
const gasLimit = (estimatedGas * GAS_LIMIT_MULTIPLIER_NUMERATOR + GAS_LIMIT_MULTIPLIER_DENOMINATOR - 1n) / GAS_LIMIT_MULTIPLIER_DENOMINATOR;
|
|
455
|
+
this.logDebug("using buffered gas limit", {
|
|
456
|
+
stepId: step.id,
|
|
457
|
+
estimatedGas: estimatedGas.toString(),
|
|
458
|
+
gasLimit: gasLimit.toString()
|
|
459
|
+
});
|
|
460
|
+
await context.onExecuteStep?.(effectiveStep.kind === "approval" ? "approval" : "transaction");
|
|
461
|
+
const txHash = await walletClient.sendTransaction({
|
|
462
|
+
...txRequest,
|
|
463
|
+
gas: gasLimit
|
|
464
|
+
});
|
|
465
|
+
const receipt = await publicClient.waitForTransactionReceipt({
|
|
466
|
+
hash: txHash
|
|
467
|
+
});
|
|
468
|
+
if (receipt.status !== "success") {
|
|
469
|
+
if (effectiveStep.kind === "dex_swap") {
|
|
470
|
+
throw new Error(this.buildDexSwapRevertMessage(route, effectiveStep.venue, txHash));
|
|
473
471
|
}
|
|
474
|
-
|
|
472
|
+
throw new Error(`EVM step transaction reverted (${effectiveStep.kind}) with hash ${txHash}`);
|
|
475
473
|
}
|
|
474
|
+
return { txHash };
|
|
476
475
|
}
|
|
477
476
|
async executeBtcTransferStep(step, context) {
|
|
478
477
|
const sendBitcoin = this.requireSendBitcoin(context);
|
|
@@ -515,6 +514,17 @@ class RiftSdk {
|
|
|
515
514
|
rift: swap
|
|
516
515
|
};
|
|
517
516
|
}
|
|
517
|
+
buildDexSwapRevertMessage(route, venue, txHash) {
|
|
518
|
+
const venueLabel = this.resolveDexVenueLabel(venue);
|
|
519
|
+
const baseMessage = route?.type === "dex_then_rift" ? `The pre-swap into cbBTC failed on ${venueLabel}; consider increasing slippage tolerance.` : `The DEX swap failed on ${venueLabel}; consider increasing slippage tolerance.`;
|
|
520
|
+
return txHash ? `${baseMessage} Transaction hash: ${txHash}` : baseMessage;
|
|
521
|
+
}
|
|
522
|
+
resolveDexVenueLabel(venue) {
|
|
523
|
+
if (typeof venue !== "string")
|
|
524
|
+
return "the selected venue";
|
|
525
|
+
const trimmed = venue.trim();
|
|
526
|
+
return trimmed.length > 0 ? trimmed : "the selected venue";
|
|
527
|
+
}
|
|
518
528
|
async assertSufficientBalance(currency, amount, context) {
|
|
519
529
|
if (currency.chain.kind !== "EVM")
|
|
520
530
|
return;
|