Skip to content

Add Bridge.Onramp functions + port old functions #7076

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 54 commits into from
May 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
efc4687
[SDK] Feature: Switch buyWithCrypto to Universal Bridge service
gregfromstl May 15, 2025
6744d0a
[SDK] Feature: Add Bridge.Transfer module
gregfromstl May 15, 2025
77ad035
changeset
gregfromstl May 15, 2025
2c33488
Merge branch 'main' into greg/tool-4362-switch-payembed-to-ub-service
gregfromstl May 15, 2025
02b1c4a
[SDK] Update Routes endpoint for transaction pay modal
gregfromstl May 15, 2025
8112650
changeset
gregfromstl May 15, 2025
dfe29f0
lint
gregfromstl May 15, 2025
421d959
chore: use configured bridge domain
gregfromstl May 15, 2025
cdaf130
max limit, domains
joaquim-verges May 16, 2025
91de2cc
add icon, duration
joaquim-verges May 16, 2025
727d0e9
fix approval, minimal status adapter
joaquim-verges May 16, 2025
abd77ec
refactor: update import for Transfer module in getTransfer.ts
gregfromstl May 16, 2025
1b00833
Merge branch 'greg/tool-4506-update-routes-endpoint' of https://githu…
gregfromstl May 16, 2025
6eff0e0
[Docs] Stylus dev workflow (#7060)
kumaryash90 May 15, 2025
ea05f7d
[SDK] Export prepareUserOp and add support for new wallets (#7061)
joaquim-verges May 15, 2025
57ecf61
[Vault] default to engine-cloud vault proxy (#7058)
d4mr May 15, 2025
05516bd
[Docs] Engine (#7057)
saminacodes May 16, 2025
267feda
[DOCS] fix link in contributing.md (#7063)
gap-editor May 16, 2025
c4a9fac
[Engine] Add FAILED status to execution result and update error handl…
joaquim-verges May 16, 2025
a7c1257
[Engine] Add all testnets to test transaction options (#7066)
joaquim-verges May 16, 2025
378993b
[Docs] Engine Update (#7052)
saminacodes May 16, 2025
e701530
[SDK] Fix buyWithCrypto false not respected when returning from quote…
joaquim-verges May 16, 2025
4bc4caf
[Dashboard] Add pagination to server wallets page (#7070)
joaquim-verges May 16, 2025
b953056
Version Packages (#7042)
joaquim-verges May 16, 2025
72bc53b
[SDK] Update package READMEs with correct naming and documentation li…
joaquim-verges May 16, 2025
c6af295
Prioritize JWT over service API keys in authentication (#7020)
jnsdls May 16, 2025
58ca5f7
chore: Update Accelerate features list (#7053)
arcoraven May 17, 2025
b128358
Version Packages (#7073)
joaquim-verges May 17, 2025
6d8d185
[Dashboard] Remove taint for THIRDWEB_ENGINE_URL (#7074)
joaquim-verges May 17, 2025
197d85b
update status endpoint
joaquim-verges May 17, 2025
8aa198b
fix 0 balance issue
joaquim-verges May 17, 2025
638dddc
lint
joaquim-verges May 17, 2025
2e6ad54
Merge remote-tracking branch 'origin' into greg/tool-4506-update-rout…
joaquim-verges May 17, 2025
4eeca27
fix
joaquim-verges May 17, 2025
8bcecf5
fix test
joaquim-verges May 17, 2025
f989121
remove tx history, show 0 fees for now
joaquim-verges May 18, 2025
a2a8723
onramp endpoint wrapper
joaquim-verges May 19, 2025
c2bbb0d
status
joaquim-verges May 19, 2025
cec95b0
export
joaquim-verges May 19, 2025
e89ff31
adapt buyWithFiat legacy function
joaquim-verges May 19, 2025
7da5372
Merge remote-tracking branch 'origin/main' into joaquim/onramp
joaquim-verges May 19, 2025
2b2b6cc
remove kado, fixes
joaquim-verges May 19, 2025
a1f5b91
state cleanup
joaquim-verges May 19, 2025
1c64203
update status legacy function
joaquim-verges May 19, 2025
388eeb9
changeset
joaquim-verges May 19, 2025
751746c
lint
joaquim-verges May 19, 2025
df465f1
remove test
joaquim-verges May 19, 2025
696bff4
fix exports
joaquim-verges May 19, 2025
f3cb4a0
export type
joaquim-verges May 19, 2025
3d912bd
more export
joaquim-verges May 19, 2025
de79cf9
comments
joaquim-verges May 19, 2025
11dc870
fix test
joaquim-verges May 20, 2025
3545b1a
tsdoc
joaquim-verges May 20, 2025
d194566
fix test
joaquim-verges May 20, 2025
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
79 changes: 79 additions & 0 deletions .changeset/tidy-seas-sing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
---
"thirdweb": patch
---

Added Bridge.Onramp.prepare and Bridge.Onramp.status functions

## Bridge.Onramp.prepare

Prepares an onramp transaction, returning a link from the specified provider to onramp to the specified token.

```typescript
import { Bridge } from "thirdweb";
import { ethereum } from "thirdweb/chains";
import { NATIVE_TOKEN_ADDRESS, toWei } from "thirdweb/utils";

const preparedOnramp = await Bridge.Onramp.prepare({
client: thirdwebClient,
onramp: "stripe",
chainId: ethereum.id,
tokenAddress: NATIVE_TOKEN_ADDRESS,
receiver: "0x...", // receiver's address
amount: toWei("10"), // 10 of the destination token
// Optional params:
// sender: "0x...", // sender's address
// onrampTokenAddress: NATIVE_TOKEN_ADDRESS, // token to initially onramp to
// onrampChainId: 1, // chain to initially onramp to
// currency: "USD",
// maxSteps: 2,
// purchaseData: { customId: "123" }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should include an optional country param in case calling from the server

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw i dont think the ip country detection works, its letting me see stripe stuff which is not available in NZ

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it does either and I don't know why

});

console.log(preparedOnramp.link); // URL to redirect the user to
console.log(preparedOnramp.currencyAmount); // Price in fiat currency
```

## Bridge.Onramp.status

Retrieves the status of an Onramp session created via Bridge.Onramp.prepare.

```typescript
import { Bridge } from "thirdweb";

const onrampStatus = await Bridge.Onramp.status({
id: "022218cc-96af-4291-b90c-dadcb47571ec",
client: thirdwebClient,
});

// Possible results:
// {
// status: "CREATED",
// transactions: [],
// purchaseData: {
// orderId: "abc-123",
// },
// }
//
// or
// {
// status: "PENDING",
// transactions: [],
// purchaseData: {
// orderId: "abc-123",
// },
// }
//
// or
// {
// status: "COMPLETED",
// transactions: [
// {
// chainId: 1,
// transactionHash: "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
// },
// ],
// purchaseData: {
// orderId: "abc-123",
// },
// }
```
2 changes: 1 addition & 1 deletion apps/portal/src/app/pay/customization/payembed/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ You can specify which onramp provider to present to your users. By default, we c
<PayEmbed
client={client}
payOptions={{
preferredProvider: "STRIPE" | "KADO" | "TRANSAK",
preferredProvider: "COINBASE" | "STRIPE" | "TRANSAK",
}}
/>
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ You can specify which onramp provider to present to your users. By default, we c
```tsx
const { mutate: sendTransaction } = useSendTransaction({
payModal: {
preferredProvider: "STRIPE" | "KADO" | "TRANSAK",
preferredProvider: "COINBASE" | "STRIPE" | "TRANSAK",
},
});
```
Expand Down
2 changes: 1 addition & 1 deletion apps/portal/src/app/pay/testing-pay/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Developers can turn on Test Mode to test both fiat-to-crypto transactions and cr

## Buy With Fiat

By setting `testMode` to `true` for Buy With Fiat, you can enable test experiences for our underlying providers (Stripe, Kado, and Transak).
By setting `testMode` to `true` for Buy With Fiat, you can enable test experiences for our underlying providers (Coinbase, Stripe, and Transak).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't true at the moment

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, we'll have to fix that :D pretty important


<Tabs defaultValue="connectbutton">

Expand Down
118 changes: 118 additions & 0 deletions packages/thirdweb/src/bridge/Onramp.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import { toWei } from "src/utils/units.js";
import { describe, expect, it } from "vitest";
import { TEST_CLIENT } from "~test/test-clients.js";
import * as Onramp from "./Onramp.js";

// Use the same receiver address as other bridge tests
const RECEIVER_ADDRESS = "0x2a4f24F935Eb178e3e7BA9B53A5Ee6d8407C0709";
const NATIVE_TOKEN_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";

/**
* These tests call the real Bridge Onramp API. They are executed only when a
* `TW_SECRET_KEY` environment variable is present, mirroring the behaviour of
* the other bridge tests in this package.
*/
describe.runIf(process.env.TW_SECRET_KEY)("Bridge.Onramp.prepare", () => {
it("should prepare an onramp successfully", async () => {
const prepared = await Onramp.prepare({
client: TEST_CLIENT,
onramp: "stripe",
chainId: 1,
tokenAddress: NATIVE_TOKEN_ADDRESS,
receiver: RECEIVER_ADDRESS,
amount: toWei("0.01"),
});

expect(prepared).toBeDefined();

// The destinationAmount should be a bigint and greater than zero
expect(typeof prepared.destinationAmount).toBe("bigint");
expect(prepared.destinationAmount > 0n).toBe(true);

// A redirect link for the user should be provided
expect(prepared.link).toBeDefined();
expect(typeof prepared.link).toBe("string");

// Intent must be present and reference the correct receiver
expect(prepared.intent).toBeDefined();
expect(prepared.intent.receiver.toLowerCase()).toBe(
RECEIVER_ADDRESS.toLowerCase(),
);

// Steps array should be defined (it may be empty if the provider supports the destination token natively)
expect(Array.isArray(prepared.steps)).toBe(true);
});

it("should surface any errors", async () => {
await expect(
Onramp.prepare({
client: TEST_CLIENT,
onramp: "stripe",
chainId: 444, // Unsupported chain ID
tokenAddress: NATIVE_TOKEN_ADDRESS,
receiver: RECEIVER_ADDRESS,
amount: toWei("0.01"),
}),
).rejects.toThrowError();
});

it("should prepare a Coinbase onramp successfully", async () => {
const prepared = await Onramp.prepare({
client: TEST_CLIENT,
onramp: "coinbase",
chainId: 1,
tokenAddress: NATIVE_TOKEN_ADDRESS,
receiver: RECEIVER_ADDRESS,
amount: toWei("0.01"),
});

expect(prepared).toBeDefined();

// The destinationAmount should be a bigint and greater than zero
expect(typeof prepared.destinationAmount).toBe("bigint");
expect(prepared.destinationAmount > 0n).toBe(true);

// A redirect link for the user should be provided
expect(prepared.link).toBeDefined();
expect(typeof prepared.link).toBe("string");

// Intent must be present and reference the correct receiver
expect(prepared.intent).toBeDefined();
expect(prepared.intent.receiver.toLowerCase()).toBe(
RECEIVER_ADDRESS.toLowerCase(),
);

// Steps array should be defined (it may be empty if the provider supports the destination token natively)
expect(Array.isArray(prepared.steps)).toBe(true);
});

it("should prepare a Transak onramp successfully", async () => {
const prepared = await Onramp.prepare({
client: TEST_CLIENT,
onramp: "transak",
chainId: 1,
tokenAddress: NATIVE_TOKEN_ADDRESS,
receiver: RECEIVER_ADDRESS,
amount: toWei("0.01"),
});

expect(prepared).toBeDefined();

// The destinationAmount should be a bigint and greater than zero
expect(typeof prepared.destinationAmount).toBe("bigint");
expect(prepared.destinationAmount > 0n).toBe(true);

// A redirect link for the user should be provided
expect(prepared.link).toBeDefined();
expect(typeof prepared.link).toBe("string");

// Intent must be present and reference the correct receiver
expect(prepared.intent).toBeDefined();
expect(prepared.intent.receiver.toLowerCase()).toBe(
RECEIVER_ADDRESS.toLowerCase(),
);

// Steps array should be defined (it may be empty if the provider supports the destination token natively)
expect(Array.isArray(prepared.steps)).toBe(true);
});
});
Loading
Loading