Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .changeset/forty-states-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
"thirdweb": patch
---

Adds the `maxSteps` option to Buy.quote, Buy.prepare, Sell.quote, and Sell.prepare functions. This allows users to limit quotes to routes with a specific number of steps or fewer. For example:

```ts
const quote = await bridge.Buy.quote({
originChainId: 1,
originTokenAddress: "0x...",
destinationChainId: 137,
destinationTokenAddress: "0x...",
amount: 1000000n,
maxSteps: 2
});

const preparedQuote = await bridge.Buy.prepare({
originChainId: 1,
originTokenAddress: "0x...",
destinationChainId: 137,
destinationTokenAddress: "0x...",
amount: 1000000n,
sender: "0x...",
receiver: "0x...",
maxSteps: 2
});

const quote = await bridge.Sell.quote({
originChainId: 1,
originTokenAddress: "0x...",
destinationChainId: 137,
destinationTokenAddress: "0x...",
amount: 1000000n,
maxSteps: 3
});

const preparedQuote = await bridge.Sell.prepare({
originChainId: 1,
originTokenAddress: "0x...",
destinationChainId: 137,
destinationTokenAddress: "0x...",
amount: 1000000n,
sender: "0x...",
receiver: "0x...",
maxSteps: 3
});
```
36 changes: 36 additions & 0 deletions packages/thirdweb/src/bridge/Buy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,23 @@ describe.runIf(process.env.TW_SECRET_KEY)("Bridge.Buy.quote", () => {
}),
).rejects.toThrowError();
});

it("should limit quotes to routes with a certain number of steps", async () => {
const quote = await Buy.quote({
originChainId: 1,
originTokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
destinationChainId: 10,
destinationTokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
amount: toWei("0.01"),
maxSteps: 2,
client: TEST_CLIENT,
});

expect(quote).toBeDefined();
expect(quote.destinationAmount).toEqual(toWei("0.01"));
expect(quote.intent).toBeDefined();
expect(quote.steps.length).toBeLessThanOrEqual(2);
});
});

describe.runIf(process.env.TW_SECRET_KEY)("Bridge.Buy.prepare", () => {
Expand Down Expand Up @@ -72,4 +89,23 @@ describe.runIf(process.env.TW_SECRET_KEY)("Bridge.Buy.prepare", () => {
}),
).rejects.toThrowError();
});

it("should limit quotes to routes with a certain number of steps", async () => {
const quote = await Buy.prepare({
originChainId: 1,
originTokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
destinationChainId: 10,
destinationTokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
amount: toWei("0.01"),
maxSteps: 2,
sender: "0x2a4f24F935Eb178e3e7BA9B53A5Ee6d8407C0709",
receiver: "0x2a4f24F935Eb178e3e7BA9B53A5Ee6d8407C0709",
client: TEST_CLIENT,
});

expect(quote).toBeDefined();
expect(quote.destinationAmount).toEqual(toWei("0.01"));
expect(quote.steps.length).toBeLessThanOrEqual(2);
expect(quote.intent).toBeDefined();
});
});
56 changes: 55 additions & 1 deletion packages/thirdweb/src/bridge/Buy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Address as ox__Address } from "ox";
import { defineChain } from "../chains/utils.js";
import type { ThirdwebClient } from "../client/client.js";
import { getClientFetch } from "../utils/fetch.js";
import { stringify } from "../utils/json.js";
import { UNIVERSAL_BRIDGE_URL } from "./constants.js";
import type { PreparedQuote, Quote } from "./types/Quote.js";

Expand Down Expand Up @@ -70,6 +71,20 @@ import type { PreparedQuote, Quote } from "./types/Quote.js";
*
* You can access this functions input and output types with `Buy.quote.Options` and `Buy.quote.Result`, respectively.
*
* To limit quotes to routes that have a certain number of steps involved, use the `maxSteps` option.
*
* ```ts
* const quote = await Bridge.Buy.quote({
* originChainId: 1,
* originTokenAddress: NATIVE_TOKEN_ADDRESS,
* destinationChainId: 10,
* destinationTokenAddress: NATIVE_TOKEN_ADDRESS,
* amount: toWei("0.01"),
* maxSteps: 2, // Will only return a quote for routes with 2 or fewer steps
* client: thirdwebClient,
* });
* ```
*
* @param options - The options for the quote.
* @param options.originChainId - The chain ID of the origin token.
* @param options.originTokenAddress - The address of the origin token.
Expand All @@ -91,6 +106,7 @@ export async function quote(options: quote.Options): Promise<quote.Result> {
destinationChainId,
destinationTokenAddress,
client,
maxSteps,
} = options;
const amount =
"buyAmountWei" in options ? options.buyAmountWei : options.amount;
Expand All @@ -102,6 +118,9 @@ export async function quote(options: quote.Options): Promise<quote.Result> {
url.searchParams.set("destinationChainId", destinationChainId.toString());
url.searchParams.set("destinationTokenAddress", destinationTokenAddress);
url.searchParams.set("buyAmountWei", amount.toString());
if (maxSteps) {
url.searchParams.set("maxSteps", maxSteps.toString());
}

const response = await clientFetch(url.toString());
if (!response.ok) {
Expand Down Expand Up @@ -137,6 +156,7 @@ export declare namespace quote {
destinationChainId: number;
destinationTokenAddress: ox__Address.Address;
client: ThirdwebClient;
maxSteps?: number;
} & (
| {
buyAmountWei: bigint;
Expand Down Expand Up @@ -247,6 +267,37 @@ export declare namespace quote {
*
* You can access this functions input and output types with `Buy.prepare.Options` and `Buy.prepare.Result`, respectively.
*
* You can include arbitrary data to be included on any webhooks and status responses with the `purchaseData` option.
*
* ```ts
* const quote = await Bridge.Buy.prepare({
* originChainId: 1,
* originTokenAddress: NATIVE_TOKEN_ADDRESS,
* destinationChainId: 10,
* destinationTokenAddress: NATIVE_TOKEN_ADDRESS,
* amount: toWei("0.01"),
* purchaseData: {
* size: "large",
* shippingAddress: "123 Main St, New York, NY 10001",
* },
* client: thirdwebClient,
* });
* ```
*
* To limit quotes to routes that have a certain number of steps involved, use the `maxSteps` option.
*
* ```ts
* const quote = await Bridge.Buy.prepare({
* originChainId: 1,
* originTokenAddress: NATIVE_TOKEN_ADDRESS,
* destinationChainId: 10,
* destinationTokenAddress: NATIVE_TOKEN_ADDRESS,
* amount: toWei("0.01"),
* maxSteps: 2, // Will only return a quote for routes with 2 or fewer steps
* client: thirdwebClient,
* });
* ```
*
* @param options - The options for the quote.
* @param options.originChainId - The chain ID of the origin token.
* @param options.originTokenAddress - The address of the origin token.
Expand Down Expand Up @@ -277,6 +328,7 @@ export async function prepare(
client,
amount,
purchaseData,
maxSteps,
} = options;

const clientFetch = getClientFetch(client);
Expand All @@ -287,7 +339,7 @@ export async function prepare(
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
body: stringify({
buyAmountWei: amount.toString(),
originChainId: originChainId.toString(),
originTokenAddress,
Expand All @@ -296,6 +348,7 @@ export async function prepare(
sender,
receiver,
purchaseData,
maxSteps,
}),
});
if (!response.ok) {
Expand Down Expand Up @@ -342,6 +395,7 @@ export declare namespace prepare {
amount: bigint;
client: ThirdwebClient;
purchaseData?: unknown;
maxSteps?: number;
};

type Result = PreparedQuote & {
Expand Down
36 changes: 36 additions & 0 deletions packages/thirdweb/src/bridge/Sell.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,23 @@ describe.runIf(process.env.TW_SECRET_KEY)("Bridge.Sell.quote", () => {
}),
).rejects.toThrowError();
});

it("should limit quotes to routes with a certain number of steps", async () => {
const quote = await Sell.quote({
originChainId: 1,
originTokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
destinationChainId: 10,
destinationTokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
amount: toWei("0.01"),
maxSteps: 2,
client: TEST_CLIENT,
});

expect(quote).toBeDefined();
expect(quote.originAmount).toEqual(toWei("0.01"));
expect(quote.intent).toBeDefined();
expect(quote.steps.length).toBeLessThanOrEqual(2);
});
});

describe.runIf(process.env.TW_SECRET_KEY)("Bridge.Sell.prepare", () => {
Expand Down Expand Up @@ -69,4 +86,23 @@ describe.runIf(process.env.TW_SECRET_KEY)("Bridge.Sell.prepare", () => {
}),
).rejects.toThrowError();
});

it("should limit quotes to routes with a certain number of steps", async () => {
const quote = await Sell.prepare({
originChainId: 1,
originTokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
destinationChainId: 10,
destinationTokenAddress: "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE",
amount: toWei("0.01"),
maxSteps: 2,
sender: "0x2a4f24F935Eb178e3e7BA9B53A5Ee6d8407C0709",
receiver: "0x2a4f24F935Eb178e3e7BA9B53A5Ee6d8407C0709",
client: TEST_CLIENT,
});

expect(quote).toBeDefined();
expect(quote.originAmount).toEqual(toWei("0.01"));
expect(quote.steps.length).toBeLessThanOrEqual(2);
expect(quote.intent).toBeDefined();
});
});
56 changes: 55 additions & 1 deletion packages/thirdweb/src/bridge/Sell.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import type { Address as ox__Address } from "ox";
import { defineChain } from "../chains/utils.js";
import type { ThirdwebClient } from "../client/client.js";
import { getClientFetch } from "../utils/fetch.js";
import { stringify } from "../utils/json.js";
import { UNIVERSAL_BRIDGE_URL } from "./constants.js";
import type { PreparedQuote, Quote } from "./types/Quote.js";

Expand Down Expand Up @@ -70,6 +71,20 @@ import type { PreparedQuote, Quote } from "./types/Quote.js";
*
* You can access this functions input and output types with `Sell.quote.Options` and `Sell.quote.Result`, respectively.
*
* To limit quotes to routes that have a certain number of steps involved, use the `maxSteps` option.
*
* ```ts
* const quote = await Bridge.Sell.quote({
* originChainId: 1,
* originTokenAddress: NATIVE_TOKEN_ADDRESS,
* destinationChainId: 10,
* destinationTokenAddress: NATIVE_TOKEN_ADDRESS,
* amount: toWei("0.01"),
* maxSteps: 2, // Will only return a quote for routes with 2 or fewer steps
* client: thirdwebClient,
* });
* ```
*
* @param options - The options for the quote.
* @param options.originChainId - The chain ID of the origin token.
* @param options.originTokenAddress - The address of the origin token.
Expand All @@ -92,6 +107,7 @@ export async function quote(options: quote.Options): Promise<quote.Result> {
destinationTokenAddress,
amount,
client,
maxSteps,
} = options;

const clientFetch = getClientFetch(client);
Expand All @@ -101,6 +117,9 @@ export async function quote(options: quote.Options): Promise<quote.Result> {
url.searchParams.set("destinationChainId", destinationChainId.toString());
url.searchParams.set("destinationTokenAddress", destinationTokenAddress);
url.searchParams.set("sellAmountWei", amount.toString());
if (typeof maxSteps !== "undefined") {
url.searchParams.set("maxSteps", maxSteps.toString());
}

const response = await clientFetch(url.toString());
if (!response.ok) {
Expand Down Expand Up @@ -136,6 +155,7 @@ export declare namespace quote {
destinationTokenAddress: ox__Address.Address;
amount: bigint;
client: ThirdwebClient;
maxSteps?: number;
};

type Result = Quote & {
Expand Down Expand Up @@ -238,6 +258,37 @@ export declare namespace quote {
*
* You can access this functions input and output types with `Sell.prepare.Options` and `Sell.prepare.Result`, respectively.
*
* You can include arbitrary data to be included on any webhooks and status responses with the `purchaseData` option.
*
* ```ts
* const quote = await Bridge.Sell.prepare({
* originChainId: 1,
* originTokenAddress: NATIVE_TOKEN_ADDRESS,
* destinationChainId: 10,
* destinationTokenAddress: NATIVE_TOKEN_ADDRESS,
* amount: toWei("0.01"),
* purchaseData: {
* size: "large",
* shippingAddress: "123 Main St, New York, NY 10001",
* },
* client: thirdwebClient,
* });
* ```
*
* To limit quotes to routes that have a certain number of steps involved, use the `maxSteps` option.
*
* ```ts
* const quote = await Bridge.Sell.prepare({
* originChainId: 1,
* originTokenAddress: NATIVE_TOKEN_ADDRESS,
* destinationChainId: 10,
* destinationTokenAddress: NATIVE_TOKEN_ADDRESS,
* amount: toWei("0.01"),
* maxSteps: 2, // Will only return a quote for routes with 2 or fewer steps
* client: thirdwebClient,
* });
* ```
*
* @param options - The options for the quote.
* @param options.originChainId - The chain ID of the origin token.
* @param options.originTokenAddress - The address of the origin token.
Expand Down Expand Up @@ -268,6 +319,7 @@ export async function prepare(
receiver,
client,
purchaseData,
maxSteps,
} = options;

const clientFetch = getClientFetch(client);
Expand All @@ -278,7 +330,7 @@ export async function prepare(
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
body: stringify({
sellAmountWei: amount.toString(),
originChainId: originChainId.toString(),
originTokenAddress,
Expand All @@ -287,6 +339,7 @@ export async function prepare(
sender,
receiver,
purchaseData,
maxSteps,
}),
});
if (!response.ok) {
Expand Down Expand Up @@ -335,6 +388,7 @@ export declare namespace prepare {
receiver: ox__Address.Address;
client: ThirdwebClient;
purchaseData?: unknown;
maxSteps?: number;
};

type Result = PreparedQuote & {
Expand Down
Loading