-
Notifications
You must be signed in to change notification settings - Fork 619
[SDK] Init new API namespaces #7637
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,41 @@ | ||
| import { createThirdwebClient } from "../../client/client.js"; | ||
|
|
||
| /** | ||
| * Initializes a new Thirdweb client using your client ID or secret key. | ||
| * @param options - Options for initializing the client | ||
| * @param options.clientId - The client ID for your Thirdweb project | ||
| * @param options.secretKey - The secret key for your Thirdweb project | ||
| * @returns A new Thirdweb client instance to be used with other thirdweb functions | ||
| * | ||
| * @example | ||
| * ## Initialize client-side | ||
| * ```typescript | ||
| * import { Client } from "thirdweb/v2"; | ||
| * | ||
| * const thirdwebClient = Client.init({ | ||
| * clientId: "YOUR_CLIENT_ID", | ||
| * }); | ||
| * ``` | ||
| * | ||
| * ## Initialize server-side | ||
| * ```typescript | ||
| * import { createThirdwebClient } from "thirdweb/v2"; | ||
| * | ||
| * const thirdwebClient = createThirdwebClient({ | ||
| * secretKey: "YOUR_CLIENT_ID", | ||
| * }); | ||
| * ``` | ||
| */ | ||
| export function init(options: init.Options) { | ||
| return createThirdwebClient(options); | ||
| } | ||
|
|
||
| export declare namespace init { | ||
| type Options = { | ||
| clientId: string; | ||
| secretKey?: string; | ||
| } | { | ||
| clientId?: string; | ||
| secretKey: string; | ||
| }; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| import { getTransactionById } from "@thirdweb-dev/api"; | ||
| import type { ThirdwebClient } from "../../client/client.js"; | ||
| import { getThirdwebBaseUrl } from "../../utils/domains.js"; | ||
| import { getClientFetch } from "../../utils/fetch.js"; | ||
| import type { Transaction } from "./types.js"; | ||
| import type { Address } from "../../utils/address.js"; | ||
| import type { Hex } from "../../utils/encoding/hex.js"; | ||
|
|
||
| /** | ||
| * Retrieves a transaction by ID. | ||
| * | ||
| * @param options - Options including the transaction ID | ||
| * @param options.transactionId - The ID of the transaction to retrieve | ||
| * @returns Promise that resolves to the transaction | ||
| * @example | ||
| * | ||
| * ## Get a transaction by ID | ||
| * ```typescript | ||
| * import { Client, Transactions } from "thirdweb/v2"; | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thinking more and more that we can get away with just import from "thirdweb" with the new namespaces. Just so much simpler. over time we can deprecate/move things out of the main export |
||
| * | ||
| * const client = Client.init({ | ||
| * clientId: "YOUR_CLIENT_ID", | ||
| * }); | ||
| * | ||
| * const transaction = await Transactions.get({ | ||
| * transactionId: "...", | ||
| * client, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| export async function get(options: get.Options): Promise<get.Result> { | ||
| const result = await getTransactionById({ | ||
| baseUrl: getThirdwebBaseUrl("api"), | ||
| fetch: getClientFetch(options.client), | ||
| path: { | ||
| transactionId: options.transactionId, | ||
| } | ||
| }); | ||
|
|
||
| if (result.error) { | ||
| throw new Error( | ||
| `Failed to get transaction: ${result.response.status} - ${result.error}`, | ||
| ); | ||
| } | ||
| const transaction = result.data?.result; | ||
| if (!transaction) { | ||
| throw new Error("Failed to get transaction: no transaction"); | ||
| } | ||
|
|
||
| return { | ||
| id: transaction.id, | ||
| transactionHash: transaction.transactionHash as Hex, | ||
| from: transaction.from as Address, | ||
| chainId: transaction.chainId, | ||
| createdAt: transaction.createdAt, | ||
| confirmedAt: transaction.confirmedAt, | ||
| confirmedAtBlockNumber: transaction.confirmedAtBlockNumber, | ||
| cancelledAt: transaction.cancelledAt, | ||
| errorMessage: transaction.errorMessage, | ||
| }; | ||
| } | ||
|
|
||
| export declare namespace get { | ||
| type Options = { | ||
| transactionId: string; | ||
| client: ThirdwebClient; | ||
| }; | ||
|
|
||
| type Result = Transaction; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| import { listTransactions } from "@thirdweb-dev/api"; | ||
| import type { Transaction } from "./types.js"; | ||
| import { getThirdwebBaseUrl } from "../../utils/domains.js"; | ||
| import { getClientFetch } from "../../utils/fetch.js"; | ||
| import type { Address } from "../../utils/address.js"; | ||
| import type { ThirdwebClient } from "../../client/client.js"; | ||
| import type { Hex } from "../../utils/encoding/hex.js"; | ||
|
|
||
|
|
||
| /** | ||
| * Retrieves a paginated list of transactions associated with the provided sender address. | ||
| * | ||
| * @param options - Options including the sender address, chain ID, and pagination | ||
| * @param options.client - The Thirdweb client instance | ||
| * @param options.sender - The sender address to retrieve transactions for | ||
| * @param options.limit - The maximum number of transactions to retrieve (default: 20, max: 100) | ||
| * @param options.page - The page number for pagination (default: 1, min: 1) | ||
| * @returns Promise that resolves to the transactions | ||
| * @example | ||
| * | ||
| * ## List transactions | ||
| * ```typescript | ||
| * import { Client, Transactions } from "thirdweb/v2"; | ||
| * | ||
| * const client = Client.init({ | ||
| * clientId: "YOUR_CLIENT_ID", | ||
| * }); | ||
| * | ||
| * const transactions = await Transactions.list({ | ||
| * sender: "0x...", | ||
| * client, | ||
| * }); | ||
| * ``` | ||
| */ | ||
| export async function list(options: list.Options): Promise<list.Result> { | ||
| const result = await listTransactions({ | ||
| baseUrl: getThirdwebBaseUrl("api"), | ||
| fetch: getClientFetch(options.client), | ||
| query: { | ||
| from: options.sender, | ||
| limit: options.limit, | ||
| page: options.page, | ||
| } | ||
| }); | ||
|
|
||
| if (result.error) { | ||
| throw new Error( | ||
| `Failed to list transactions: ${result.response.status} - ${result.error}`, | ||
| ); | ||
| } | ||
| const transactions = result.data?.result?.transactions; | ||
| if (!transactions) { | ||
| throw new Error("Failed to list transactions: no transactions"); | ||
| } | ||
| return transactions.map((transaction) => ({ | ||
| id: transaction.id, | ||
| transactionHash: transaction.transactionHash as Hex, | ||
| from: transaction.from as Address, | ||
| chainId: transaction.chainId, | ||
| createdAt: transaction.createdAt, | ||
| confirmedAt: transaction.confirmedAt, | ||
| confirmedAtBlockNumber: transaction.confirmedAtBlockNumber, | ||
| cancelledAt: transaction.cancelledAt, | ||
| errorMessage: transaction.errorMessage, | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. thinking we probably need a 'status' top level here, in the API too |
||
| })); | ||
| } | ||
|
|
||
| export declare namespace list { | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Uppercase? |
||
| type Options = { | ||
| client: ThirdwebClient; | ||
| sender: Address; | ||
| limit?: number; | ||
| page?: number; | ||
| }; | ||
|
|
||
| type Result = Array<Transaction>; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,141 @@ | ||
| import { sendTransactions } from "@thirdweb-dev/api"; | ||
| import type { UserWallet } from "../wallets/types.js"; | ||
| import type { TransactionRequest } from "./types.js"; | ||
| import { getThirdwebBaseUrl } from "../../utils/domains.js"; | ||
| import { getClientFetch } from "../../utils/fetch.js"; | ||
|
|
||
| /** | ||
| * Sends a series of transactions for execution. Each transaction can be a human-readable contract call, native transfer, or encoded transaction. | ||
| * | ||
| * @param options - Options including the wallet, chain id, and transactions | ||
| * @param options.wallet - The wallet to use for signing transactions | ||
| * @param options.chainId - The chain ID to use for the transactions | ||
| * @param options.transactions - An array of transactions to send | ||
| * @returns The sent transaction IDs | ||
| * @example | ||
| * | ||
| * ## Call a contract | ||
| * ```typescript | ||
| * import { Client, Transactions, Wallets } from "thirdweb/v2"; | ||
| * | ||
| * const userWallet = await Wallets.loginWithOauth({ | ||
| * client: thirdwebClient, | ||
| * provider: "google", | ||
| * }); | ||
| * | ||
| * const transactionIds = await Transactions.send({ | ||
| * wallet: userWallet, | ||
| * chainId: 1, | ||
| * transactions: [ | ||
| * { | ||
| * contractAddress: "0x...", | ||
| * method: "function transfer(address,uint256)", | ||
| * params: ["0x...", 100n], | ||
| * } | ||
| * ], | ||
| * }); | ||
| * ``` | ||
| * | ||
| * ## Send native currency | ||
| * ```typescript | ||
| * import { Client, Transactions, Wallets } from "thirdweb/v2"; | ||
| * | ||
| * const userWallet = await Wallets.loginAsGuest({ | ||
| * client: thirdwebClient, | ||
| * }); | ||
| * | ||
| * const transactionIds = await Transactions.send({ | ||
| * wallet: userWallet, | ||
| * chainId: 1, | ||
| * transactions: [ | ||
| * { | ||
| * to: "0x...", | ||
| * value: 100n, | ||
| * } | ||
| * ], | ||
| * }); | ||
| * ``` | ||
| * | ||
| * ## Send an encoded transaction | ||
| * ```typescript | ||
| * import { Client, Transactions, Wallets } from "thirdweb/v2"; | ||
| * | ||
| * const thirdwebClient = Client.init({ | ||
| * clientId: "YOUR_CLIENT_ID", | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you're not initializing the client in the other 2 examples |
||
| * }); | ||
| * | ||
| * const userWallet = await Wallets.loginWithOauth({ | ||
| * client: thirdwebClient, | ||
| * provider: "github", | ||
| * }); | ||
| * | ||
| * const transactionIds = await Transactions.send({ | ||
| * wallet: userWallet, | ||
| * chainId: 1, | ||
| * transactions: [ | ||
| * { | ||
| * to: "0x...", | ||
| * data: "0x...", | ||
| * } | ||
| * ], | ||
| * }); | ||
| */ | ||
| export async function send(options: send.Options): Promise<Array<string>> { | ||
| const transactions = options.transactions.map((transaction) => { | ||
| if ("contractAddress" in transaction) { | ||
| return { | ||
| contractAddress: transaction.contractAddress, | ||
| method: transaction.method, | ||
| params: transaction.params, | ||
| value: transaction.value?.toString() ?? "0", | ||
| type: "contract-call" as const, | ||
| } as const; | ||
| } else if ("data" in transaction) { | ||
| return { | ||
| to: transaction.to, | ||
| data: transaction.data, | ||
| value: transaction.value?.toString() ?? "0", | ||
| type: "encoded" as const, | ||
| } as const; | ||
| } else { | ||
| return { | ||
| to: transaction.to, | ||
| value: transaction.value?.toString() ?? "0", | ||
| type: "native-transfer" as const, | ||
| } as const; | ||
| } | ||
| }); | ||
|
|
||
| const result = await sendTransactions({ | ||
| baseUrl: getThirdwebBaseUrl("api"), | ||
| fetch: getClientFetch(options.wallet.client), | ||
| headers: { | ||
| Authorization: `Bearer ${options.wallet.authToken}`, | ||
| }, | ||
| body: { | ||
| chainId: options.chainId, | ||
| from: options.wallet.address, | ||
| transactions | ||
| } | ||
| }); | ||
|
|
||
| if (result.error) { | ||
| throw new Error( | ||
| `Failed to send transactions: ${result.response.status} - ${result.error}`, | ||
| ); | ||
| } | ||
| const transactionIds = result.data?.result?.transactionIds; | ||
| if (!transactionIds) { | ||
| throw new Error("Failed to send transactions: no transaction ids"); | ||
| } | ||
| return transactionIds; | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. tempted to change the API to be a single transaction id, feels simpler |
||
| }; | ||
|
|
||
| export namespace send { | ||
| export type Options = { | ||
| wallet: UserWallet; | ||
| chainId: number; | ||
| transactions: Array<TransactionRequest>; | ||
| }; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| import type { Address } from "../../utils/address.js"; | ||
| import type { Hex } from "../../utils/encoding/hex.js"; | ||
|
|
||
| export type TransactionRequest = { | ||
| contractAddress: Address; | ||
| method: `function ${string}`; | ||
| params: Array<(string | bigint | number | boolean | object)>; | ||
| value?: bigint; | ||
| } | { | ||
| to: Address; | ||
| data: Hex; | ||
| value?: bigint; | ||
| } | { | ||
| to: Address; | ||
| value: bigint; | ||
| } | ||
|
|
||
| export type Transaction = { | ||
| id: string; | ||
| transactionHash: Hex; | ||
| from: Address; | ||
| chainId: string; | ||
| createdAt: string; | ||
| confirmedAt?: string; | ||
| confirmedAtBlockNumber?: string; | ||
| cancelledAt?: string; | ||
| errorMessage: string | null; | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| export type EthereumAddress = `0x${string}`; // Joaquim do you think we should use the types from the existing SDK or create entirely new ones so we don't cross over at all? | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think if we keep things namespaced we can get away with new types. but tbh for addresses i still fill like 0x{string} is overkill. super annoying when you get back nested structs from api that you're just trying to feed back into a typed function. I would just use string, and validate at runtime |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,10 +8,10 @@ export { | |
| loginWithOauthRedirect, | ||
| } from "./oauth.js"; | ||
| export { | ||
| loginWithCode as verifyCode, | ||
| type SendCodeOptions, | ||
| sendCode, | ||
| type VerifyCodeOptions, | ||
| verifyLoginCode, | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not loginWithCode? |
||
| type SendLoginCodeOptions, | ||
| sendLoginCode, | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we can do sendVerificationCode if you think sendCode is confusing |
||
| type VerifyLoginCodeOptions, | ||
| } from "./otp.js"; | ||
| export { type LoginWithPasskeyOptions, loginWithPasskey } from "./passkey.js"; | ||
| export { type LoginWithWalletOptions, loginWithWallet } from "./siwe.js"; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reminder to fix this example