Skip to content

Commit 4608466

Browse files
committed
feat: adds transaction functions
1 parent 5483874 commit 4608466

File tree

9 files changed

+396
-37
lines changed

9 files changed

+396
-37
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { createThirdwebClient } from "../../client/client.js";
2+
3+
/**
4+
* Initializes a new Thirdweb client using your client ID or secret key.
5+
* @param options - Options for initializing the client
6+
* @param options.clientId - The client ID for your Thirdweb project
7+
* @param options.secretKey - The secret key for your Thirdweb project
8+
* @returns A new Thirdweb client instance to be used with other thirdweb functions
9+
*
10+
* @example
11+
* ## Initialize client-side
12+
* ```typescript
13+
* import { Client } from "thirdweb/v2";
14+
*
15+
* const thirdwebClient = Client.init({
16+
* clientId: "YOUR_CLIENT_ID",
17+
* });
18+
* ```
19+
*
20+
* ## Initialize server-side
21+
* ```typescript
22+
* import { createThirdwebClient } from "thirdweb/v2";
23+
*
24+
* const thirdwebClient = createThirdwebClient({
25+
* secretKey: "YOUR_CLIENT_ID",
26+
* });
27+
* ```
28+
*/
29+
export function init(options: init.Options) {
30+
return createThirdwebClient(options);
31+
}
32+
33+
export declare namespace init {
34+
type Options = {
35+
clientId: string;
36+
secretKey?: string;
37+
} | {
38+
clientId?: string;
39+
secretKey: string;
40+
};
41+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { getTransactionById } from "@thirdweb-dev/api";
2+
import type { ThirdwebClient } from "../../client/client.js";
3+
import { getThirdwebBaseUrl } from "../../utils/domains.js";
4+
import { getClientFetch } from "../../utils/fetch.js";
5+
import type { Transaction } from "./types.js";
6+
import type { Address } from "../../utils/address.js";
7+
import type { Hex } from "../../utils/encoding/hex.js";
8+
9+
/**
10+
* Retrieves a transaction by ID.
11+
*
12+
* @param options - Options including the transaction ID
13+
* @param options.transactionId - The ID of the transaction to retrieve
14+
* @returns Promise that resolves to the transaction
15+
* @example
16+
*
17+
* ## Get a transaction by ID
18+
* ```typescript
19+
* import { Client, Transactions } from "thirdweb/v2";
20+
*
21+
* const client = Client.init({
22+
* clientId: "YOUR_CLIENT_ID",
23+
* });
24+
*
25+
* const transaction = await Transactions.get({
26+
* transactionId: "...",
27+
* client,
28+
* });
29+
* ```
30+
*/
31+
export async function get(options: get.Options): Promise<get.Result> {
32+
const result = await getTransactionById({
33+
baseUrl: getThirdwebBaseUrl("api"),
34+
fetch: getClientFetch(options.client),
35+
path: {
36+
transactionId: options.transactionId,
37+
}
38+
});
39+
40+
if (result.error) {
41+
throw new Error(
42+
`Failed to get transaction: ${result.response.status} - ${result.error}`,
43+
);
44+
}
45+
const transaction = result.data?.result;
46+
if (!transaction) {
47+
throw new Error("Failed to get transaction: no transaction");
48+
}
49+
50+
return {
51+
id: transaction.id,
52+
transactionHash: transaction.transactionHash as Hex,
53+
from: transaction.from as Address,
54+
chainId: transaction.chainId,
55+
createdAt: transaction.createdAt,
56+
confirmedAt: transaction.confirmedAt,
57+
confirmedAtBlockNumber: transaction.confirmedAtBlockNumber,
58+
cancelledAt: transaction.cancelledAt,
59+
errorMessage: transaction.errorMessage,
60+
};
61+
}
62+
63+
export declare namespace get {
64+
type Options = {
65+
transactionId: string;
66+
client: ThirdwebClient;
67+
};
68+
69+
type Result = Transaction;
70+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { listTransactions } from "@thirdweb-dev/api";
2+
import type { Transaction } from "./types.js";
3+
import { getThirdwebBaseUrl } from "../../utils/domains.js";
4+
import { getClientFetch } from "../../utils/fetch.js";
5+
import type { Address } from "../../utils/address.js";
6+
import type { ThirdwebClient } from "../../client/client.js";
7+
import type { Hex } from "../../utils/encoding/hex.js";
8+
9+
10+
/**
11+
* Retrieves a paginated list of transactions associated with the provided sender address.
12+
*
13+
* @param options - Options including the sender address, chain ID, and pagination
14+
* @param options.client - The Thirdweb client instance
15+
* @param options.sender - The sender address to retrieve transactions for
16+
* @param options.limit - The maximum number of transactions to retrieve (default: 20, max: 100)
17+
* @param options.page - The page number for pagination (default: 1, min: 1)
18+
* @returns Promise that resolves to the transactions
19+
* @example
20+
*
21+
* ## List transactions
22+
* ```typescript
23+
* import { Client, Transactions } from "thirdweb/v2";
24+
*
25+
* const client = Client.init({
26+
* clientId: "YOUR_CLIENT_ID",
27+
* });
28+
*
29+
* const transactions = await Transactions.list({
30+
* sender: "0x...",
31+
* client,
32+
* });
33+
* ```
34+
*/
35+
export async function list(options: list.Options): Promise<list.Result> {
36+
const result = await listTransactions({
37+
baseUrl: getThirdwebBaseUrl("api"),
38+
fetch: getClientFetch(options.client),
39+
query: {
40+
from: options.sender,
41+
limit: options.limit,
42+
page: options.page,
43+
}
44+
});
45+
46+
if (result.error) {
47+
throw new Error(
48+
`Failed to list transactions: ${result.response.status} - ${result.error}`,
49+
);
50+
}
51+
const transactions = result.data?.result?.transactions;
52+
if (!transactions) {
53+
throw new Error("Failed to list transactions: no transactions");
54+
}
55+
return transactions.map((transaction) => ({
56+
id: transaction.id,
57+
transactionHash: transaction.transactionHash as Hex,
58+
from: transaction.from as Address,
59+
chainId: transaction.chainId,
60+
createdAt: transaction.createdAt,
61+
confirmedAt: transaction.confirmedAt,
62+
confirmedAtBlockNumber: transaction.confirmedAtBlockNumber,
63+
cancelledAt: transaction.cancelledAt,
64+
errorMessage: transaction.errorMessage,
65+
}));
66+
}
67+
68+
export declare namespace list {
69+
type Options = {
70+
client: ThirdwebClient;
71+
sender: Address;
72+
limit?: number;
73+
page?: number;
74+
};
75+
76+
type Result = Array<Transaction>;
77+
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
import { sendTransactions } from "@thirdweb-dev/api";
2+
import type { UserWallet } from "../wallets/types.js";
3+
import type { TransactionRequest } from "./types.js";
4+
import { getThirdwebBaseUrl } from "../../utils/domains.js";
5+
import { getClientFetch } from "../../utils/fetch.js";
6+
7+
/**
8+
* Sends a series of transactions for execution. Each transaction can be a human-readable contract call, native transfer, or encoded transaction.
9+
*
10+
* @param options - Options including the wallet, chain id, and transactions
11+
* @param options.wallet - The wallet to use for signing transactions
12+
* @param options.chainId - The chain ID to use for the transactions
13+
* @param options.transactions - An array of transactions to send
14+
* @returns The sent transaction IDs
15+
* @example
16+
*
17+
* ## Call a contract
18+
* ```typescript
19+
* import { Client, Transactions, Wallets } from "thirdweb/v2";
20+
*
21+
* const userWallet = await Wallets.loginWithOauth({
22+
* client: thirdwebClient,
23+
* provider: "google",
24+
* });
25+
*
26+
* const transactionIds = await Transactions.send({
27+
* wallet: userWallet,
28+
* chainId: 1,
29+
* transactions: [
30+
* {
31+
* contractAddress: "0x...",
32+
* method: "function transfer(address,uint256)",
33+
* params: ["0x...", 100n],
34+
* }
35+
* ],
36+
* });
37+
* ```
38+
*
39+
* ## Send native currency
40+
* ```typescript
41+
* import { Client, Transactions, Wallets } from "thirdweb/v2";
42+
*
43+
* const userWallet = await Wallets.loginAsGuest({
44+
* client: thirdwebClient,
45+
* });
46+
*
47+
* const transactionIds = await Transactions.send({
48+
* wallet: userWallet,
49+
* chainId: 1,
50+
* transactions: [
51+
* {
52+
* to: "0x...",
53+
* value: 100n,
54+
* }
55+
* ],
56+
* });
57+
* ```
58+
*
59+
* ## Send an encoded transaction
60+
* ```typescript
61+
* import { Client, Transactions, Wallets } from "thirdweb/v2";
62+
*
63+
* const thirdwebClient = Client.init({
64+
* clientId: "YOUR_CLIENT_ID",
65+
* });
66+
*
67+
* const userWallet = await Wallets.loginWithOauth({
68+
* client: thirdwebClient,
69+
* provider: "github",
70+
* });
71+
*
72+
* const transactionIds = await Transactions.send({
73+
* wallet: userWallet,
74+
* chainId: 1,
75+
* transactions: [
76+
* {
77+
* to: "0x...",
78+
* data: "0x...",
79+
* }
80+
* ],
81+
* });
82+
*/
83+
export async function send(options: send.Options): Promise<Array<string>> {
84+
const transactions = options.transactions.map((transaction) => {
85+
if ("contractAddress" in transaction) {
86+
return {
87+
contractAddress: transaction.contractAddress,
88+
method: transaction.method,
89+
params: transaction.params,
90+
value: transaction.value?.toString() ?? "0",
91+
type: "contract-call" as const,
92+
} as const;
93+
} else if ("data" in transaction) {
94+
return {
95+
to: transaction.to,
96+
data: transaction.data,
97+
value: transaction.value?.toString() ?? "0",
98+
type: "encoded" as const,
99+
} as const;
100+
} else {
101+
return {
102+
to: transaction.to,
103+
value: transaction.value?.toString() ?? "0",
104+
type: "native-transfer" as const,
105+
} as const;
106+
}
107+
});
108+
109+
const result = await sendTransactions({
110+
baseUrl: getThirdwebBaseUrl("api"),
111+
fetch: getClientFetch(options.wallet.client),
112+
headers: {
113+
Authorization: `Bearer ${options.wallet.authToken}`,
114+
},
115+
body: {
116+
chainId: options.chainId,
117+
from: options.wallet.address,
118+
transactions
119+
}
120+
});
121+
122+
if (result.error) {
123+
throw new Error(
124+
`Failed to send transactions: ${result.response.status} - ${result.error}`,
125+
);
126+
}
127+
const transactionIds = result.data?.result?.transactionIds;
128+
if (!transactionIds) {
129+
throw new Error("Failed to send transactions: no transaction ids");
130+
}
131+
return transactionIds;
132+
};
133+
134+
export namespace send {
135+
export type Options = {
136+
wallet: UserWallet;
137+
chainId: number;
138+
transactions: Array<TransactionRequest>;
139+
};
140+
}
141+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import type { Address } from "../../utils/address.js";
2+
import type { Hex } from "../../utils/encoding/hex.js";
3+
4+
export type TransactionRequest = {
5+
contractAddress: Address;
6+
method: `function ${string}`;
7+
params: Array<(string | bigint | number | boolean | object)>;
8+
value?: bigint;
9+
} | {
10+
to: Address;
11+
data: Hex;
12+
value?: bigint;
13+
} | {
14+
to: Address;
15+
value: bigint;
16+
}
17+
18+
export type Transaction = {
19+
id: string;
20+
transactionHash: Hex;
21+
from: Address;
22+
chainId: string;
23+
createdAt: string;
24+
confirmedAt?: string;
25+
confirmedAtBlockNumber?: string;
26+
cancelledAt?: string;
27+
errorMessage: string | null;
28+
}
29+

packages/thirdweb/src/v2/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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?

packages/thirdweb/src/v2/wallets/index.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ export {
88
loginWithOauthRedirect,
99
} from "./oauth.js";
1010
export {
11-
loginWithCode as verifyCode,
12-
type SendCodeOptions,
13-
sendCode,
14-
type VerifyCodeOptions,
11+
verifyLoginCode,
12+
type SendLoginCodeOptions,
13+
sendLoginCode,
14+
type VerifyLoginCodeOptions,
1515
} from "./otp.js";
1616
export { type LoginWithPasskeyOptions, loginWithPasskey } from "./passkey.js";
1717
export { type LoginWithWalletOptions, loginWithWallet } from "./siwe.js";

packages/thirdweb/src/v2/wallets/login.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ describe.skip("login tests", () => {
1818
clientId: "...",
1919
});
2020

21-
await Wallets.sendCode({
21+
await Wallets.sendLoginCode({
2222
client,
2323
type: "phone",
2424
phoneNumber: "+1111111111",
2525
});
2626

27-
const wallet = await Wallets.verifyCode({
27+
const wallet = await Wallets.verifyLoginCode({
2828
client,
2929
type: "phone",
3030
phoneNumber: "+1111111111",

0 commit comments

Comments
 (0)