From 4184c7e0f7fe5c6207dfde0ea13282de6ee2517a Mon Sep 17 00:00:00 2001
From: Philippe d'Argent
Date: Mon, 24 Mar 2025 20:36:12 +0100
Subject: [PATCH] add skipWaitingForFill option to executeQuote
---
apps/example/package.json | 2 +-
apps/example/scripts/sdk-testnet.ts | 108 +++++++++++++++++++++++
packages/sdk/src/actions/executeQuote.ts | 10 +++
3 files changed, 119 insertions(+), 1 deletion(-)
create mode 100644 apps/example/scripts/sdk-testnet.ts
diff --git a/apps/example/package.json b/apps/example/package.json
index 92c29a3..cef3172 100644
--- a/apps/example/package.json
+++ b/apps/example/package.json
@@ -8,7 +8,7 @@
"start": "next start",
"lint": "next lint",
"sdk": "tsx ./scripts/sdk.ts",
- "sdk-ethers": "tsx ./scripts/sdk-ethers.ts",
+ "sdk-testnet": "tsx ./scripts/sdk-testnet.ts",
"ci": "pnpm run build && pnpm run lint"
},
"dependencies": {
diff --git a/apps/example/scripts/sdk-testnet.ts b/apps/example/scripts/sdk-testnet.ts
new file mode 100644
index 0000000..8eacd50
--- /dev/null
+++ b/apps/example/scripts/sdk-testnet.ts
@@ -0,0 +1,108 @@
+import { AcrossClient } from "@across-protocol/app-sdk";
+import {
+ Hex,
+ http,
+ createWalletClient,
+ parseUnits,
+ createPublicClient,
+} from "viem";
+import { privateKeyToAccount } from "viem/accounts";
+import { sepolia, baseSepolia } from "viem/chains";
+import { loadEnvConfig } from "@next/env";
+
+const projectDir = process.cwd();
+loadEnvConfig(projectDir);
+
+// test using client with node
+async function main() {
+ const chains = [sepolia, baseSepolia];
+
+ const PRIVATE_KEY = process.env.DEV_PK
+ ? (process.env.DEV_PK as Hex)
+ : undefined;
+
+ if (!PRIVATE_KEY) {
+ throw new Error("No Private key in ENV");
+ }
+
+ // Read RPC URLs from environment variables
+ const ORIGIN_RPC_URL = process.env.ORIGIN_RPC_URL ;
+ const DESTINATION_RPC_URL = process.env.DESTINATION_RPC_URL;
+
+ // Create a viem wallet client using the private key
+ const account = privateKeyToAccount(PRIVATE_KEY);
+ console.log("Account address: ", account.address);
+
+ const walletClient = createWalletClient({
+ account,
+ chain: sepolia,
+ transport: ORIGIN_RPC_URL ? http(ORIGIN_RPC_URL) : http(),
+ });
+
+ const client = AcrossClient.create({
+ chains,
+ useTestnet: true,
+ logLevel: "ERROR",
+ walletClient,
+ });
+
+ const routeInfo = await client.getAvailableRoutes({
+ originChainId: sepolia.id,
+ destinationChainId: baseSepolia.id,
+ originToken: "0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14", // ETH
+ });
+
+ // Select route
+ console.log(routeInfo);
+ const route = routeInfo[1]; // isNative route
+
+ if (!route) {
+ throw new Error("No routes");
+ }
+
+ const bridgeQuoteRes = await client.getQuote({
+ route,
+ inputAmount: parseUnits("0.00015", 18),
+ });
+ console.log(bridgeQuoteRes);
+
+ const originClient = createPublicClient({
+ chain: sepolia,
+ transport: ORIGIN_RPC_URL ? http(ORIGIN_RPC_URL) : http(),
+ });
+
+ const destinationClient = createPublicClient({
+ chain: baseSepolia,
+ transport: DESTINATION_RPC_URL ? http(DESTINATION_RPC_URL) : http(),
+ });
+
+ const result = await client.executeQuote({
+ walletClient,
+ deposit: bridgeQuoteRes.deposit,
+ originClient: originClient as any,
+ destinationClient: destinationClient as any,
+ onProgress: (progress) => {
+ if (progress.step === "approve" && progress.status === "txSuccess") {
+ // if approving an ERC20, you have access to the approval receipt
+ const { txReceipt } = progress;
+ console.log("Approve successful: ", txReceipt);
+ }
+ if (progress.step === "deposit" && progress.status === "txSuccess") {
+ // once deposit is successful you have access to depositId and the receipt
+ const { depositId, txReceipt } = progress;
+ console.log("Deposit with id: ", depositId);
+ console.log("Deposit Transaction Hash: ", txReceipt.transactionHash);
+ }
+ if (progress.step === "fill" && progress.status === "txSuccess") {
+ // if the fill is successful, you have access the following data
+ const { fillTxTimestamp, txReceipt, actionSuccess } = progress;
+ console.log("Fill Transaction Hash: ", txReceipt.transactionHash);
+ console.log("Action success: ", actionSuccess);
+ // actionSuccess is a boolean flag, telling us if your cross chain messages were successful
+ }
+ },
+ infiniteApproval: false,
+ skipWaitingForFill: true,
+ });
+}
+main();
diff --git a/packages/sdk/src/actions/executeQuote.ts b/packages/sdk/src/actions/executeQuote.ts
index d874ec4..ecc643f 100644
--- a/packages/sdk/src/actions/executeQuote.ts
+++ b/packages/sdk/src/actions/executeQuote.ts
@@ -145,6 +145,10 @@ export type ExecuteQuoteParams = {
* Whether to skip the allowance check.
*/
skipAllowanceCheck?: boolean;
+ /**
+ * Whether to skip waiting for the fill transaction.
+ */
+ skipWaitingForFill?: boolean;
/**
* Whether to throw if an error occurs.
*/
@@ -185,6 +189,7 @@ export async function executeQuote(params: ExecuteQuoteParams) {
forceOriginChain,
onProgress,
logger,
+ skipWaitingForFill = false,
} = params;
const onProgressHandler =
@@ -360,6 +365,11 @@ export async function executeQuote(params: ExecuteQuoteParams) {
};
onProgressHandler(currentTransactionProgress);
+ // Return after deposit is confirmed if so configured
+ if (skipWaitingForFill) {
+ return { depositId, depositTxReceipt };
+ }
+
// After successful deposit, wait for fill
currentProgressMeta = {
depositId,