Compare commits

..
Author SHA1 Message Date
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
f3c55d7139 Version Packages (#8240)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-10-11 19:31:58 +07:00
Prithvish BaidyaandGitHub 9545b43675 Engine SDK updates (#8238) 2025-10-11 19:24:30 +07:00
Joaquim VergesGitHubgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
869bbcfa68 Version Packages (#8237)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-10-11 07:42:22 +07:00
Prithvish BaidyaandGitHub 35c7d21e36 [Vault SDK] Add Solana operations support (#8168) 2025-10-11 07:37:27 +07:00
MananTank edf3aad8c4 [BLD-396] Dashboard: Fix changing tabs in /nfts/<id> page shows full page loading indicator (#8224)
<!--

## title your PR with this format: "[SDK/Dashboard/Portal] Feature/Fix: Concise title for the changes"

If you did not copy the branch name from Linear, paste the issue tag here (format is TEAM-0000):

## Notes for the reviewer

Anything important to call out? Be sure to also clarify these in your comments.

## How to test

Unit tests, playground, etc.

-->

<!-- start pr-codex -->

---

## PR-Codex overview
This PR enhances the `TokenIdPage` component by introducing `Suspense` for improved loading state handling and adjusting the layout of the loading spinner.

### Detailed summary
- Added `Suspense` for handling loading states.
- Updated the loading spinner layout with additional padding (`py-20`).
- Wrapped the tab rendering logic within the `Suspense` component for better user experience during data fetching.

> ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}`

<!-- end pr-codex -->

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- New Features
  - Introduced a loading experience for NFT tab content using Suspense, providing a fallback UI while content loads.
  - Improves responsiveness when switching tabs by deferring heavy content until ready.

- Style
  - Increased vertical padding for the pending NFT state to enhance visual spacing and readability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-10-09 22:14:06 +00:00
24 changed files with 4191 additions and 48 deletions
@@ -2,7 +2,7 @@
import { ExternalLinkIcon } from "lucide-react";
import Link from "next/link";
import { useState } from "react";
import { Suspense, useState } from "react";
import type { NFT, ThirdwebClient, ThirdwebContract } from "thirdweb";
import { getNFT as getErc721NFT } from "thirdweb/extensions/erc721";
import { getNFT as getErc1155NFT } from "thirdweb/extensions/erc1155";
@@ -89,7 +89,7 @@ export const TokenIdPage: React.FC<TokenIdPageProps> = ({
if (isPending) {
return (
<div className="flex h-[400px] items-center justify-center">
<div className="flex h-[400px] items-center justify-center py-20">
<Spinner className="size-10" />
</div>
);
@@ -179,15 +179,26 @@ export const TokenIdPage: React.FC<TokenIdPageProps> = ({
<NFTDetailsTab client={contract.client} nft={nft} />
)}
{tabs.map((tb) => {
return (
tb.title === tab && (
<div className="w-full" key={tb.title}>
{tb.children}
<Suspense
fallback={
<div className="h-full">
<div className="flex items-center gap-1.5">
<Spinner className="size-4" />
<p className="text-sm text-muted-foreground"> Loading </p>
</div>
)
);
})}
</div>
}
>
{tabs.map((tb) => {
return (
tb.title === tab && (
<div className="w-full" key={tb.title}>
{tb.children}
</div>
)
);
})}
</Suspense>
</div>
</div>
</div>
+8
View File
@@ -1,5 +1,13 @@
# wagmi-inapp
## 0.0.8
### Patch Changes
- Updated dependencies []:
- thirdweb@5.108.13
- @thirdweb-dev/wagmi-adapter@0.2.163
## 0.0.7
### Patch Changes
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "wagmi-inapp",
"private": true,
"version": "0.0.7",
"version": "0.0.8",
"type": "module",
"scripts": {
"dev": "vite",
+6
View File
@@ -1,5 +1,11 @@
# @thirdweb-dev/engine
## 3.3.0
### Minor Changes
- [#8238](https://github.com/thirdweb-dev/js/pull/8238) [`9545b43`](https://github.com/thirdweb-dev/js/commit/9545b4367598408dbb88c63d8a8fe21305f870b5) Thanks [@d4mr](https://github.com/d4mr)! - Add Solana endpoints
## 3.2.2
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@thirdweb-dev/engine",
"version": "3.2.2",
"version": "3.3.0",
"repository": {
"type": "git",
"url": "git+https://github.com/thirdweb-dev/js.git#main"
+251
View File
@@ -11,11 +11,18 @@ import type {
CancelTransactionResponses,
CreateAccountData,
CreateAccountResponses,
CreateSolanaAccountData,
CreateSolanaAccountResponses,
EncodeContractData,
EncodeContractResponses,
GetActivityLogsData,
GetActivityLogsErrors,
GetActivityLogsResponses,
GetSolanaActivityLogsData,
GetSolanaActivityLogsErrors,
GetSolanaActivityLogsResponses,
GetSolanaTransactionsData,
GetSolanaTransactionsResponses,
GetTransactionAnalyticsData,
GetTransactionAnalyticsResponses,
GetTransactionAnalyticsSummaryData,
@@ -25,17 +32,30 @@ import type {
GetTransactionsResponses,
ListAccountsData,
ListAccountsResponses,
ListSolanaAccountsData,
ListSolanaAccountsResponses,
ReadContractData,
ReadContractResponses,
SearchActivityLogsData,
SearchActivityLogsErrors,
SearchActivityLogsResponses,
SearchSolanaActivityLogsData,
SearchSolanaActivityLogsErrors,
SearchSolanaActivityLogsResponses,
SearchSolanaTransactionsData,
SearchSolanaTransactionsResponses,
SearchTransactionsData,
SearchTransactionsResponses,
SendSolanaTransactionData,
SendSolanaTransactionResponses,
SendTransactionData,
SendTransactionResponses,
SignMessageData,
SignMessageResponses,
SignSolanaMessageData,
SignSolanaMessageResponses,
SignSolanaTransactionData,
SignSolanaTransactionResponses,
SignTypedDataData,
SignTypedDataResponses,
WriteContractData,
@@ -227,6 +247,33 @@ export const encodeContract = <ThrowOnError extends boolean = false>(
});
};
/**
* Send Solana Transaction
* Execute a Solana transaction with custom instructions
*/
export const sendSolanaTransaction = <ThrowOnError extends boolean = false>(
options: Options<SendSolanaTransactionData, ThrowOnError>,
) => {
return (options.client ?? _heyApiClient).post<
SendSolanaTransactionResponses,
unknown,
ThrowOnError
>({
security: [
{
name: "x-secret-key",
type: "apiKey",
},
],
url: "/v1/solana/transaction",
...options,
headers: {
"Content-Type": "application/json",
...options.headers,
},
});
};
/**
* Cancel Transaction
* Attempt to cancel a queued transaction. Transactions that have been sent and are waiting for mine cannot be cancelled.
@@ -300,6 +347,110 @@ export const createAccount = <ThrowOnError extends boolean = false>(
});
};
/**
* List Solana Accounts
* List all Solana wallets provisioned for the project.
*/
export const listSolanaAccounts = <ThrowOnError extends boolean = false>(
options?: Options<ListSolanaAccountsData, ThrowOnError>,
) => {
return (options?.client ?? _heyApiClient).get<
ListSolanaAccountsResponses,
unknown,
ThrowOnError
>({
security: [
{
name: "x-secret-key",
type: "apiKey",
},
],
url: "/v1/solana/accounts",
...options,
});
};
/**
* Get or Create Solana Account
* Create a new solana wallet in the vault or return the existing wallet for a given label.
*/
export const createSolanaAccount = <ThrowOnError extends boolean = false>(
options?: Options<CreateSolanaAccountData, ThrowOnError>,
) => {
return (options?.client ?? _heyApiClient).post<
CreateSolanaAccountResponses,
unknown,
ThrowOnError
>({
security: [
{
name: "x-secret-key",
type: "apiKey",
},
],
url: "/v1/solana/accounts",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers,
},
});
};
/**
* Sign Solana Message
* Sign an arbitrary message with a Solana wallet.
*/
export const signSolanaMessage = <ThrowOnError extends boolean = false>(
options?: Options<SignSolanaMessageData, ThrowOnError>,
) => {
return (options?.client ?? _heyApiClient).post<
SignSolanaMessageResponses,
unknown,
ThrowOnError
>({
security: [
{
name: "x-secret-key",
type: "apiKey",
},
],
url: "/v1/solana/sign-message",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers,
},
});
};
/**
* Sign Solana Transaction
* Sign a serialized Solana transaction.
*/
export const signSolanaTransaction = <ThrowOnError extends boolean = false>(
options?: Options<SignSolanaTransactionData, ThrowOnError>,
) => {
return (options?.client ?? _heyApiClient).post<
SignSolanaTransactionResponses,
unknown,
ThrowOnError
>({
security: [
{
name: "x-secret-key",
type: "apiKey",
},
],
url: "/v1/solana/sign-transaction",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers,
},
});
};
/**
* Get Transactions
* Search transactions with various filters and pagination
@@ -455,3 +606,103 @@ export const searchActivityLogs = <ThrowOnError extends boolean = false>(
},
});
};
/**
* Get Solana Transactions
* Search Solana transactions with various filters and pagination
*/
export const getSolanaTransactions = <ThrowOnError extends boolean = false>(
options?: Options<GetSolanaTransactionsData, ThrowOnError>,
) => {
return (options?.client ?? _heyApiClient).get<
GetSolanaTransactionsResponses,
unknown,
ThrowOnError
>({
security: [
{
name: "x-secret-key",
type: "apiKey",
},
],
url: "/v1/solana/transactions",
...options,
});
};
/**
* Search Solana Transactions
* Advanced search for Solana transactions with complex nested filters
*/
export const searchSolanaTransactions = <ThrowOnError extends boolean = false>(
options?: Options<SearchSolanaTransactionsData, ThrowOnError>,
) => {
return (options?.client ?? _heyApiClient).post<
SearchSolanaTransactionsResponses,
unknown,
ThrowOnError
>({
security: [
{
name: "x-secret-key",
type: "apiKey",
},
],
url: "/v1/solana/transactions/search",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers,
},
});
};
/**
* Get Solana Activity Logs
* Get paginated activity logs for a specific Solana transaction with tenancy enforcement
*/
export const getSolanaActivityLogs = <ThrowOnError extends boolean = false>(
options: Options<GetSolanaActivityLogsData, ThrowOnError>,
) => {
return (options.client ?? _heyApiClient).get<
GetSolanaActivityLogsResponses,
GetSolanaActivityLogsErrors,
ThrowOnError
>({
security: [
{
name: "x-secret-key",
type: "apiKey",
},
],
url: "/v1/solana/transactions/activity-logs",
...options,
});
};
/**
* Search Solana Activity Logs
* Search Solana activity logs across transactions with advanced filtering and tenancy enforcement
*/
export const searchSolanaActivityLogs = <ThrowOnError extends boolean = false>(
options?: Options<SearchSolanaActivityLogsData, ThrowOnError>,
) => {
return (options?.client ?? _heyApiClient).post<
SearchSolanaActivityLogsResponses,
SearchSolanaActivityLogsErrors,
ThrowOnError
>({
security: [
{
name: "x-secret-key",
type: "apiKey",
},
],
url: "/v1/solana/transactions/activity-logs/search",
...options,
headers: {
"Content-Type": "application/json",
...options?.headers,
},
});
};
+792
View File
@@ -17,6 +17,19 @@ export type TransactionsFilterNested = {
filters: Array<TransactionsFilterValue | TransactionsFilterNested>;
};
export type SolanaTransactionsFilterValue = {
field: "id" | "chainId" | "signerAddress" | "signature";
values: Array<string>;
operation: "AND" | "OR";
};
export type SolanaTransactionsFilterNested = {
operation: "AND" | "OR";
filters: Array<
SolanaTransactionsFilterValue | SolanaTransactionsFilterNested
>;
};
/**
* EVM Address
* Used to represent an EVM address. This is a string of length 42 with a `0x` prefix. Non-checksummed addresses are also supported, but will be converted to checksummed.
@@ -112,6 +125,21 @@ export type BatchResultItemEncodeResultSuccessItemEngineError =
kind: RpcErrorKind;
type: "BUNDLER_ERROR";
}
| {
/**
* Solana chain identifier
*/
chain_id: string;
/**
* Human-readable error message
*/
message: string;
/**
* Structured error kind
*/
kind: SolanaRpcErrorKind;
type: "SOLANA_RPC_ERROR";
}
| {
message: string;
type: "VAULT_ERROR";
@@ -202,6 +230,21 @@ export type BatchResultItemReadResultSuccessItemEngineError =
kind: RpcErrorKind;
type: "BUNDLER_ERROR";
}
| {
/**
* Solana chain identifier
*/
chain_id: string;
/**
* Human-readable error message
*/
message: string;
/**
* Structured error kind
*/
kind: SolanaRpcErrorKind;
type: "SOLANA_RPC_ERROR";
}
| {
message: string;
type: "VAULT_ERROR";
@@ -301,6 +344,21 @@ export type BatchResultItemSignResultDataEngineError =
kind: RpcErrorKind;
type: "BUNDLER_ERROR";
}
| {
/**
* Solana chain identifier
*/
chain_id: string;
/**
* Human-readable error message
*/
message: string;
/**
* Structured error kind
*/
kind: SolanaRpcErrorKind;
type: "SOLANA_RPC_ERROR";
}
| {
message: string;
type: "VAULT_ERROR";
@@ -392,6 +450,11 @@ export type CancelResult =
}
| "NOT_FOUND";
/**
* Commitment Level
*/
export type CommitmentLevel = "confirmed" | "finalized";
/**
* Represents a contract function call with parameters
*
@@ -765,6 +828,8 @@ export type InnerTransaction = (null | TransactionTypeData) & {
gasLimit?: number | null;
};
export type InstructionDataEncoding = "hex" | "base64";
export type MessageFormatDef = "text" | "hex";
/**
@@ -783,6 +848,29 @@ export type MessageInput = {
export type MulticallDocType = boolean | AddressDef;
/**
* Pubkey
*/
export type PubkeyDef = string;
/**
* Response for a queued Solana transaction
*/
export type QueuedSolanaTransactionResponse = {
/**
* The idempotency key for this transaction
*/
transactionId: string;
/**
* The Solana chain
*/
chainId: SolanaChainId;
/**
* The signer address
*/
signerAddress: string;
};
/**
* # QueuedTransaction
* Response for any request that queues one or more transactions
@@ -909,6 +997,28 @@ export type RpcErrorResponse = {
data?: string | null;
};
/**
* Request to send a Solana transaction
*/
export type SendSolanaTransactionRequest = {
/**
* Idempotency key for this transaction (defaults to random UUID)
*/
idempotencyKey?: string;
/**
* List of Solana instructions to execute
*/
instructions: Array<SolanaInstructionData>;
/**
* Solana execution options
*/
executionOptions: SolanaExecutionOptions;
/**
* Webhook options for transaction status notifications
*/
webhookOptions?: Array<WebhookOptions>;
};
/**
* Incoming transaction request, parsed into InnerTransaction
* Exposed API will have varying `params` but will all parse into InnerTransaction before execution
@@ -975,6 +1085,9 @@ export type SerialisableAwsSignerError =
| {
message: string;
type: "UNKNOWN";
}
| {
type: "SIGNATURE_RECOVERY_FAILED";
};
export type SerializableReqwestError =
@@ -1149,6 +1262,196 @@ export type SigningOptions =
chainId: number;
};
/**
* Account metadata for Solana instructions
*/
export type SolanaAccountMeta = {
/**
* Public key of the account
*/
pubkey: PubkeyDef;
/**
* Whether the account should sign the transaction
*/
isSigner: boolean;
/**
* Whether the account is writable
*/
isWritable: boolean;
};
/**
* Solana chain identifier
*/
export type SolanaChainId = "solana:mainnet" | "solana:devnet" | "solana:local";
/**
* ### Solana Execution Options
* This struct configures Solana transaction execution.
*
* Solana execution sends transactions directly to Solana RPC nodes with
* support for priority fees, compute budgets, and commitment levels.
*
* ### Use Cases
* - SOL transfers
* - SPL token operations
* - Program interactions (NFTs, DeFi, etc.)
* - Arbitrary instruction composition
*
* ### Features
* - Versioned transactions with address lookup tables
* - Priority fee configuration for faster inclusion
* - Compute budget optimization
* - Configurable commitment levels
* - Blockhash retry mechanism
*/
export type SolanaExecutionOptions = {
/**
* The Solana address (public key) to send transactions from
* This account must have sufficient SOL to pay for transaction fees
*/
signerAddress: PubkeyDef;
/**
* Solana chain to use
*/
chainId: SolanaChainId;
/**
* Maximum number of times to retry fetching a new blockhash if transaction fails
* Default: 0 (fail fast)
* Max: 1000
*/
maxBlockhashRetries?: number;
/**
* Commitment level for transaction confirmation
* Options: "processed", "confirmed", "finalized"
* Default: "finalized"
*/
commitment?: CommitmentLevel;
priorityFee?: null | SolanaPriorityFee;
/**
* Compute unit limit for the transaction. If omitted, the transaction will use the default compute unit limit. If provided, engine will add the compute budget instruction to the transaction.
*/
computeUnitLimit?: number | null;
};
/**
* Solana instruction data provided by the user
* This is a simplified representation that will be converted to a proper Instruction
*/
export type SolanaInstructionData = {
/**
* Program ID to invoke
*/
programId: PubkeyDef;
/**
* Account keys that will be passed to the program
*/
accounts: Array<SolanaAccountMeta>;
/**
* Instruction data (hex-encoded or base64)
*/
data: string;
encoding: InstructionDataEncoding;
};
/**
* Solana Priority Fee
*/
export type SolanaPriorityFee =
| {
type: "auto";
}
| {
microLamportsPerUnit: number;
type: "manual";
}
| {
percentile: number;
type: "percentile";
};
/**
* Solana-specific RPC error types
*/
export type SolanaRpcErrorKind =
| {
message: string;
kind?: string | null;
type: "IO";
}
| {
message: string;
status?: number | null;
type: "REQWEST";
}
| {
code: number;
message: string;
/**
* Structured error data from Solana RPC
*/
data: SolanaRpcResponseErrorData;
type: "RPC_ERROR";
}
| {
message: string;
line?: number | null;
column?: number | null;
type: "SERDE_JSON";
}
| {
error_type: string;
message: string;
type: "TRANSACTION_ERROR";
}
| {
message: string;
type: "SIGNING_ERROR";
}
| {
message: string;
type: "CUSTOM";
}
| {
message: string;
type: "UNKNOWN";
};
/**
* Serializable version of Solana's RpcResponseErrorData
*/
export type SolanaRpcResponseErrorData =
| {
type: "EMPTY";
}
| {
/**
* Error message from simulation
*/
err?: string | null;
/**
* Logs from simulation
*/
logs?: Array<string> | null;
/**
* Accounts used in simulation
*/
accounts?: unknown;
/**
* Units consumed during simulation
*/
units_consumed?: number | null;
/**
* Return data from the transaction
*/
return_data?: unknown;
type: "SEND_TRANSACTION_PREFLIGHT_FAILURE";
}
| {
num_slots_behind?: number | null;
type: "NODE_UNHEALTHY";
};
/**
* Execution Option Variants
* All supported specific execution options are contained here
@@ -1174,6 +1477,26 @@ export type SuccessResponseEmptyIdempotencySetResponse = {
};
};
export type SuccessResponseQueuedSolanaTransactionResponse = {
/**
* Response for a queued Solana transaction
*/
result: {
/**
* The idempotency key for this transaction
*/
transactionId: string;
/**
* The Solana chain
*/
chainId: SolanaChainId;
/**
* The signer address
*/
signerAddress: string;
};
};
export type SuccessResponseQueuedTransactionsResponse = {
result: {
transactions: Array<QueuedTransaction>;
@@ -1498,6 +1821,32 @@ export type EncodeContractResponses = {
export type EncodeContractResponse =
EncodeContractResponses[keyof EncodeContractResponses];
export type SendSolanaTransactionData = {
/**
* Solana transaction request
*/
body: SendSolanaTransactionRequest;
headers?: {
/**
* Vault access token
*/
"x-vault-access-token"?: string | null;
};
path?: never;
query?: never;
url: "/v1/solana/transaction";
};
export type SendSolanaTransactionResponses = {
/**
* Solana transaction queued successfully
*/
202: SuccessResponseQueuedSolanaTransactionResponse;
};
export type SendSolanaTransactionResponse =
SendSolanaTransactionResponses[keyof SendSolanaTransactionResponses];
export type CancelTransactionData = {
body?: never;
path: {
@@ -1598,6 +1947,178 @@ export type CreateAccountResponses = {
export type CreateAccountResponse =
CreateAccountResponses[keyof CreateAccountResponses];
export type ListSolanaAccountsData = {
body?: never;
headers?: {
/**
* Vault Access Token used to access your EOA
*/
"x-vault-access-token"?: string;
};
path?: never;
query?: {
page?: number;
limit?: number;
};
url: "/v1/solana/accounts";
};
export type ListSolanaAccountsResponses = {
/**
* Solana accounts retrieved
*/
200: {
result: {
accounts: Array<{
/**
* Base58 encoded Solana public key
*/
publicKey: string;
label?: string;
createdAt: string;
updatedAt: string;
}>;
pagination: {
totalCount: number;
page: number;
limit: number;
};
};
};
};
export type ListSolanaAccountsResponse =
ListSolanaAccountsResponses[keyof ListSolanaAccountsResponses];
export type CreateSolanaAccountData = {
body?: {
label: string;
};
headers?: {
/**
* Vault Access Token used to access your EOA
*/
"x-vault-access-token"?: string;
};
path?: never;
query?: never;
url: "/v1/solana/accounts";
};
export type CreateSolanaAccountResponses = {
/**
* Solana account retrieved
*/
200: {
result: {
/**
* Base58 encoded Solana public key
*/
publicKey: string;
label?: string;
createdAt: string;
updatedAt: string;
};
};
/**
* Solana account created
*/
201: {
result: {
/**
* Base58 encoded Solana public key
*/
publicKey: string;
label?: string;
createdAt: string;
updatedAt: string;
};
};
};
export type CreateSolanaAccountResponse =
CreateSolanaAccountResponses[keyof CreateSolanaAccountResponses];
export type SignSolanaMessageData = {
body?: {
/**
* Base58 encoded Solana public key
*/
from: string;
message: string;
format?: "text" | "hex";
};
headers?: {
/**
* Vault Access Token used to access your EOA
*/
"x-vault-access-token"?: string;
};
path?: never;
query?: never;
url: "/v1/solana/sign-message";
};
export type SignSolanaMessageResponses = {
/**
* Message signed
*/
200: {
result: {
/**
* Base58 encoded signature
*/
signature: string;
};
};
};
export type SignSolanaMessageResponse =
SignSolanaMessageResponses[keyof SignSolanaMessageResponses];
export type SignSolanaTransactionData = {
body?: {
/**
* Base58 encoded Solana public key
*/
from: string;
/**
* Base64 encoded Solana transaction
*/
transaction: string;
};
headers?: {
/**
* Vault Access Token used to access your EOA
*/
"x-vault-access-token"?: string;
};
path?: never;
query?: never;
url: "/v1/solana/sign-transaction";
};
export type SignSolanaTransactionResponses = {
/**
* Transaction signed
*/
200: {
result: {
/**
* Base58 encoded signature
*/
signature: string;
/**
* Base58 encoded Solana public key
*/
signerPublicKey: string;
};
};
};
export type SignSolanaTransactionResponse =
SignSolanaTransactionResponses[keyof SignSolanaTransactionResponses];
export type GetTransactionsData = {
body?: never;
path?: never;
@@ -1967,6 +2488,277 @@ export type SearchActivityLogsResponses = {
export type SearchActivityLogsResponse =
SearchActivityLogsResponses[keyof SearchActivityLogsResponses];
export type GetSolanaTransactionsData = {
body?: never;
path?: never;
query?: {
page?: number;
limit?: number;
id?: string;
chainId?: string;
signerAddress?: string;
signature?: string;
status?: "QUEUED" | "SUBMITTED" | "CONFIRMED" | "FAILED";
sortBy?: "createdAt" | "confirmedAt";
sortDirection?: "asc" | "desc";
};
url: "/v1/solana/transactions";
};
export type GetSolanaTransactionsResponses = {
/**
* Solana Transactions
*/
200: {
result: {
transactions: Array<{
id: string;
clientId: string;
chainId: string;
signerAddress: string;
transactionParams:
| (string | number | boolean | null)
| {
[key: string]: unknown;
}
| Array<unknown>;
signature: string | null;
status: string | null;
confirmedAt: string | null;
confirmedAtSlot: string | null;
blockTime: number | null;
enrichedData:
| (string | number | boolean | null)
| {
[key: string]: unknown;
}
| Array<unknown>;
executionParams:
| (string | number | boolean | null)
| {
[key: string]: unknown;
}
| Array<unknown>;
executionResult:
| (string | number | boolean | null)
| {
[key: string]: unknown;
}
| Array<unknown>
| null;
createdAt: string;
errorMessage: string | null;
cancelledAt: string | null;
}>;
pagination: {
totalCount: number;
page: number;
limit: number;
};
};
};
};
export type GetSolanaTransactionsResponse =
GetSolanaTransactionsResponses[keyof GetSolanaTransactionsResponses];
export type SearchSolanaTransactionsData = {
body?: {
page?: number;
limit?: number;
filters?: Array<
SolanaTransactionsFilterValue | SolanaTransactionsFilterNested
>;
filtersOperation?: "AND" | "OR";
sortBy?: "createdAt" | "confirmedAt";
sortDirection?: "asc" | "desc";
};
path?: never;
query?: never;
url: "/v1/solana/transactions/search";
};
export type SearchSolanaTransactionsResponses = {
/**
* Solana Transactions
*/
200: {
result: {
transactions: Array<{
id: string;
clientId: string;
chainId: string;
signerAddress: string;
transactionParams:
| (string | number | boolean | null)
| {
[key: string]: unknown;
}
| Array<unknown>;
signature: string | null;
status: string | null;
confirmedAt: string | null;
confirmedAtSlot: string | null;
blockTime: number | null;
enrichedData:
| (string | number | boolean | null)
| {
[key: string]: unknown;
}
| Array<unknown>;
executionParams:
| (string | number | boolean | null)
| {
[key: string]: unknown;
}
| Array<unknown>;
executionResult:
| (string | number | boolean | null)
| {
[key: string]: unknown;
}
| Array<unknown>
| null;
createdAt: string;
errorMessage: string | null;
cancelledAt: string | null;
}>;
pagination: {
totalCount: number;
page: number;
limit: number;
};
};
};
};
export type SearchSolanaTransactionsResponse =
SearchSolanaTransactionsResponses[keyof SearchSolanaTransactionsResponses];
export type GetSolanaActivityLogsData = {
body?: never;
path?: never;
query: {
page?: number;
limit?: number;
transactionId: string;
eventType?: "SUCCESS" | "FAILURE" | "NACK";
stageName?: string;
executorName?: string;
sortBy?: "timestamp" | "createdAt";
sortDirection?: "asc" | "desc";
};
url: "/v1/solana/transactions/activity-logs";
};
export type GetSolanaActivityLogsErrors = {
/**
* Invalid request parameters
*/
400: unknown;
/**
* Transaction not found or not accessible
*/
404: unknown;
};
export type GetSolanaActivityLogsResponses = {
/**
* Solana Activity Logs
*/
200: {
result: {
activityLogs: Array<{
id: string;
transactionId: string;
eventType: string;
stageName: string;
executorName: string;
notificationId: string;
payload:
| (string | number | boolean | null)
| {
[key: string]: unknown;
}
| Array<unknown>;
timestamp: string;
createdAt: string;
}>;
transaction: {
id: string;
clientId: string;
};
pagination: {
totalCount: number;
page: number;
limit: number;
};
};
};
};
export type GetSolanaActivityLogsResponse =
GetSolanaActivityLogsResponses[keyof GetSolanaActivityLogsResponses];
export type SearchSolanaActivityLogsData = {
body?: {
page?: number;
limit?: number;
transactionIds?: Array<string>;
eventType?: "SUCCESS" | "FAILURE" | "NACK";
stageName?: string;
executorName?: string;
startDate?: string;
endDate?: string;
sortBy?: "timestamp" | "createdAt";
sortDirection?: "asc" | "desc";
};
path?: never;
query?: never;
url: "/v1/solana/transactions/activity-logs/search";
};
export type SearchSolanaActivityLogsErrors = {
/**
* Invalid request parameters
*/
400: unknown;
};
export type SearchSolanaActivityLogsResponses = {
/**
* Solana Activity Logs Search Results
*/
200: {
result: {
activityLogs: Array<{
id: string;
transactionId: string;
eventType: string;
stageName: string;
executorName: string;
notificationId: string;
payload:
| (string | number | boolean | null)
| {
[key: string]: unknown;
}
| Array<unknown>;
timestamp: string;
createdAt: string;
}>;
pagination: {
totalCount: number;
page: number;
limit: number;
};
};
};
};
export type SearchSolanaActivityLogsResponse =
SearchSolanaActivityLogsResponses[keyof SearchSolanaActivityLogsResponses];
export type ClientOptions = {
baseUrl: "https://engine.thirdweb.com" | (string & {});
};
+7
View File
@@ -1,5 +1,12 @@
# @thirdweb-dev/nebula
## 0.2.66
### Patch Changes
- Updated dependencies []:
- thirdweb@5.108.13
## 0.2.65
### Patch Changes
+1 -1
View File
@@ -57,5 +57,5 @@
"type": "module",
"types": "./dist/types/exports/thirdweb.d.ts",
"typings": "./dist/types/exports/thirdweb.d.ts",
"version": "0.2.65"
"version": "0.2.66"
}
+7
View File
@@ -1,5 +1,12 @@
# thirdweb
## 5.108.13
### Patch Changes
- Updated dependencies [[`9545b43`](https://github.com/thirdweb-dev/js/commit/9545b4367598408dbb88c63d8a8fe21305f870b5)]:
- @thirdweb-dev/engine@3.3.0
## 5.108.12
### Patch Changes
+1 -1
View File
@@ -430,5 +430,5 @@
}
},
"typings": "./dist/types/exports/thirdweb.d.ts",
"version": "5.108.12"
"version": "5.108.13"
}
+6
View File
@@ -1,5 +1,11 @@
# @thirdweb-dev/react-native-adapter
## 0.1.0
### Minor Changes
- [#8168](https://github.com/thirdweb-dev/js/pull/8168) [`35c7d21`](https://github.com/thirdweb-dev/js/commit/35c7d21e368f9ea5636c8663ba31b7d473b5b343) Thanks [@d4mr](https://github.com/d4mr)! - Added Vault operations support for Solana.
## 0.0.3
### Patch Changes
+1 -13
View File
@@ -1,16 +1,4 @@
{
"$schema": "https://biomejs.dev/schemas/2.0.6/schema.json",
"extends": "//",
"overrides": [
{
"assist": {
"actions": {
"source": {
"useSortedKeys": "off"
}
}
},
"includes": ["package.json"]
}
]
"extends": "//"
}
+11 -2
View File
@@ -7,12 +7,20 @@
"@noble/ciphers": "^1.2.1",
"@noble/curves": "1.8.2",
"@noble/hashes": "1.7.2",
"@solana/addresses": "^3.0.0",
"@solana/keys": "^3.0.0",
"@solana/kit": "^4.0.0",
"@solana/rpc": "^3.0.0",
"@solana/transactions": "^3.0.0",
"abitype": "1.0.8",
"jose": "6.0.11"
},
"devDependencies": {
"@biomejs/biome": "2.0.6",
"rimraf": "6.0.1"
"@solana-program/system": "^0.8.1",
"bs58": "^6.0.0",
"rimraf": "6.0.1",
"vitest": "3.2.4"
},
"engines": {
"node": ">=18"
@@ -51,6 +59,7 @@
"build:esm": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm && printf '{\"type\": \"module\",\"sideEffects\":false}' > ./dist/esm/package.json",
"build:types": "tsc --project ./tsconfig.build.json --module esnext --declarationDir ./dist/types --emitDeclarationOnly --declaration --declarationMap",
"clean": "rimraf dist",
"test:solana": "vitest ./tests/solana.test.ts",
"dev": "tsc --project ./tsconfig.build.json --module es2020 --outDir ./dist/esm --watch",
"fix": "biome check ./src --fix",
"format": "biome format ./src --write",
@@ -59,5 +68,5 @@
"type": "module",
"types": "./dist/types/exports/thirdweb.d.ts",
"typings": "./dist/types/exports/thirdweb.d.ts",
"version": "0.0.3"
"version": "0.1.0"
}
@@ -3,15 +3,19 @@ export {
createEoa,
createServiceAccount,
createSignedAccessToken,
createSolanaAccount,
createVaultClient,
getServiceAccount,
listAccessTokens,
listEoas,
listSolanaAccounts,
ping,
revokeAccessToken,
rotateServiceAccount,
signAuthorization,
signMessage,
signSolanaMessage,
signSolanaTransaction,
signStructuredMessage,
signTransaction,
signTypedData,
@@ -31,6 +35,7 @@ export type {
CreateAccessTokenPayload,
CreateEoaPayload,
CreateServiceAccountPayload,
CreateSolanaAccountPayload,
EncryptedPayload,
GenericPayload,
GetAccessTokensData,
@@ -38,6 +43,7 @@ export type {
GetServiceAccountPayload,
ListAccessTokensPayload,
ListEoaPayload,
ListSolanaAccountsPayload,
Payload,
PingPayload,
PolicyComponent,
@@ -49,6 +55,8 @@ export type {
SignAuthorizationRules,
SignedAuthorization,
SignMessagePayload,
SignSolanaMessagePayload,
SignSolanaTransactionPayload,
SignStructuredMessageData,
SignStructuredMessageOptions,
SignStructuredMessagePayload,
+102 -1
View File
@@ -3,18 +3,27 @@ import { x25519 } from "@noble/curves/ed25519";
import { hkdf } from "@noble/hashes/hkdf";
import { sha256 } from "@noble/hashes/sha256";
import { bytesToHex, hexToBytes, randomBytes } from "@noble/hashes/utils";
import {
address,
getBase58Encoder,
getTransactionDecoder,
getTransactionEncoder,
} from "@solana/kit";
import type { TypedData } from "abitype";
import * as jose from "jose";
import type {
CheckedSignTypedDataPayload,
CreateAccessTokenPayload,
CreateEoaPayload,
CreateServiceAccountPayload,
CreateSolanaAccountPayload,
EncryptedPayload,
GetServiceAccountPayload,
ListAccessTokensPayload,
ListEoaPayload,
ListSolanaAccountsPayload,
Payload,
PingPayload,
PolicyComponent,
@@ -23,6 +32,8 @@ import type {
RotateServiceAccountPayload,
SignAuthorizationPayload,
SignMessagePayload,
SignSolanaMessagePayload,
SignSolanaTransactionPayload,
SignStructuredMessagePayload,
SignTransactionPayload,
UnencryptedErrorResponse,
@@ -447,6 +458,96 @@ export function listAccessTokens({
});
}
// ========== Solana Functions ==========
export function createSolanaAccount({
client,
request: options,
}: PayloadParams<CreateSolanaAccountPayload>) {
return sendRequest<CreateSolanaAccountPayload>({
client,
request: {
operation: "solana:create",
...options,
},
});
}
export function listSolanaAccounts({
client,
request: options,
}: PayloadParams<ListSolanaAccountsPayload>) {
return sendRequest<ListSolanaAccountsPayload>({
client,
request: {
operation: "solana:list",
...options,
},
});
}
export function signSolanaTransaction({
client,
request: options,
}: PayloadParams<SignSolanaTransactionPayload>) {
return sendRequest<SignSolanaTransactionPayload>({
client,
request: {
operation: "solana:signTransaction",
...options,
},
});
}
/**
* Reconstruct a signed solana transaction from the vault signature using @solana/kit
*/
export function reconstructSolanaSignedTransaction(
base64Transaction: string,
base58Signature: string,
signerPubkey: string,
): Uint8Array {
// Decode the base64 transaction into bytes
const base64TransactionBytes = new Uint8Array(
Buffer.from(base64Transaction, "base64"),
);
// Decode the transaction to get its structure
const transactionDecoder = getTransactionDecoder();
const transaction = transactionDecoder.decode(base64TransactionBytes);
// Decode the base58 signature to bytes
const base58Encoder = getBase58Encoder();
const signatureBytes = base58Encoder.encode(base58Signature);
// Add the signature to the transaction
const signedTransaction = {
...transaction,
signatures: {
...transaction.signatures,
[address(signerPubkey)]: signatureBytes,
},
};
// Re-encode the signed transaction
const transactionEncoder = getTransactionEncoder();
const signedTransactionBytes = transactionEncoder.encode(signedTransaction);
return new Uint8Array(signedTransactionBytes);
}
export function signSolanaMessage({
client,
request: options,
}: PayloadParams<SignSolanaMessagePayload>) {
return sendRequest<SignSolanaMessagePayload>({
client,
request: {
operation: "solana:signMessage",
...options,
},
});
}
const SIGNED_TOKEN_PREFIX = "vt_sat_";
const DEFAULT_SIGNING_CONTEXT = "encryption"; // Default context for HKDF
+154 -2
View File
@@ -58,7 +58,7 @@ export type UnencryptedErrorResponse = {
type EncryptedError = {
code: string;
message: string;
details?: string;
details?: string | { reason: string };
};
type GenericSuccessResponse<Data> = {
@@ -148,6 +148,50 @@ type SignMessageOptions = {
format?: "text" | "hex";
};
// ========== Solana Options Types ==========
// Solana message type that's compatible with both Kit and our Rust serialization
export type SolanaVersionedMessage = {
version: "legacy" | "v0";
header: {
numRequiredSignatures: number;
numReadonlySignedAccounts: number;
numReadonlyUnsignedAccounts: number;
};
staticAccountKeys: string[]; // Use string instead of SolanaAddress for simplicity
recentBlockhash: string;
instructions: Array<{
programIdIndex: number;
accountKeyIndexes: number[];
data: Uint8Array;
}>;
addressTableLookups?: Array<{
accountKey: string; // Use string instead of SolanaAddress
writableIndexes: number[];
readonlyIndexes: number[];
}>;
};
type CreateSolanaAccountOptions = {
metadata: Record<string, MetadataValue>;
};
type GetSolanaAccountsOptions = {
page?: number;
pageSize?: number;
};
type SignSolanaTransactionOptions = {
transaction: string; // Base64 encoded VersionedTransaction
from: string; // Use string for Solana public key
};
type SignSolanaMessageOptions = {
message: string;
from: string; // Use string for Solana public key
format?: "text" | "hex";
};
type CheckedSignTypedDataOptions<
Types extends TypedData,
PrimaryType extends keyof Types | "EIP712Domain" = keyof Types,
@@ -315,12 +359,63 @@ export type PolicyComponent =
useropV07?: UserOperationV07Rules;
};
}
| {
type: "solana:create";
requiredMetadataPatterns?: MetadataRule[];
allowedMetadataPatterns?: MetadataRule[];
}
| {
type: "solana:read";
metadataPatterns?: MetadataRule[];
}
| {
type: "solana:signTransaction";
allowlist?: string[]; // Use string for Solana addresses
metadataPatterns?: MetadataRule[];
payloadPatterns?: Record<string, Rule[]>;
transactionPatterns?: SolanaTransactionPatterns;
}
| {
type: "solana:signMessage";
allowlist?: string[]; // Use string for Solana addresses
metadataPatterns?: MetadataRule[];
messagePattern?: string;
}
| {
type: "accessToken:read";
metadataPatterns?: MetadataRule[];
revealSensitive: boolean;
};
// Solana transaction patterns
export type SolanaTransactionPatterns = {
programs?: ProgramAccessControl;
writableAccounts?: AccountAccessControl;
requiredCosigners?: string[];
maxInstructions?: number;
canPayFees?: boolean;
};
export type ProgramAccessControl =
| {
type: "allow";
programs: string[];
}
| {
type: "deny";
programs: string[];
};
export type AccountAccessControl =
| {
type: "allow";
accounts: string[];
}
| {
type: "deny";
accounts: string[];
};
type OwnerType = string; // Define based on your eoa models
type CreateAccessTokenOptions = {
@@ -399,6 +494,30 @@ type SignMessageData = {
signature: string;
};
// ========== Solana Data Types ==========
type CreateSolanaAccountData = {
pubkey: string;
metadata: Record<string, MetadataValue>;
createdAt: string;
updatedAt: string;
};
type GetSolanaAccountsData = {
accounts: CreateSolanaAccountData[];
totalCount: number;
page: number;
pageSize: number;
};
type SignSolanaTransactionData = {
signature: string; // Base58 encoded signature
signerPubkey: string; // Use string for Solana public key
};
type SignSolanaMessageData = {
signature: string; // Base58 encoded signature
};
type SignTypedDataData = {
signature: string;
};
@@ -553,6 +672,35 @@ export type RevokeAccessTokenPayload = GenericPayload<{
data: AccessTokenData;
}>;
// ========== Solana Payload Types ==========
export type CreateSolanaAccountPayload = GenericPayload<{
operation: "solana:create";
auth: Auth;
options: CreateSolanaAccountOptions;
data: CreateSolanaAccountData;
}>;
export type ListSolanaAccountsPayload = GenericPayload<{
operation: "solana:list";
auth: Auth;
options: GetSolanaAccountsOptions;
data: GetSolanaAccountsData;
}>;
export type SignSolanaTransactionPayload = GenericPayload<{
operation: "solana:signTransaction";
auth: Auth;
options: SignSolanaTransactionOptions;
data: SignSolanaTransactionData;
}>;
export type SignSolanaMessagePayload = GenericPayload<{
operation: "solana:signMessage";
auth: Auth;
options: SignSolanaMessageOptions;
data: SignSolanaMessageData;
}>;
// ========== Union of all payloads ==========
export type Payload =
| PingPayload
@@ -568,4 +716,8 @@ export type Payload =
| RevokeAccessTokenPayload
| SignAuthorizationPayload
| SignStructuredMessagePayload
| ListAccessTokensPayload;
| ListAccessTokensPayload
| CreateSolanaAccountPayload
| ListSolanaAccountsPayload
| SignSolanaTransactionPayload
| SignSolanaMessagePayload;
+6
View File
@@ -0,0 +1,6 @@
# Solana RPC Configuration
SOLANA_RPC_HTTP_URL=http://127.0.0.1:8899
SOLANA_RPC_WS_URL=ws://127.0.0.1:8900
# Vault Configuration
VAULT_URL=http://localhost:3000
+11
View File
@@ -0,0 +1,11 @@
import { dirname, join } from "node:path";
import { loadEnvFile } from "node:process";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
try {
loadEnvFile(join(__dirname, ".env"));
} catch (_error) {
console.warn("No .env file found, using default values");
}
File diff suppressed because it is too large Load Diff
+17
View File
@@ -0,0 +1,17 @@
import { join } from "node:path";
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globals: true,
environment: "node",
testTimeout: 60000, // 60 seconds default timeout
hookTimeout: 60000, // 60 seconds for beforeAll/afterAll
teardownTimeout: 10000,
sequence: {
shuffle: false, // Run tests in order
},
// load .env.test
setupFiles: [join(__dirname, "./tests/env-setup.ts")],
},
});
+2
View File
@@ -1,5 +1,7 @@
# @thirdweb-dev/wagmi-adapter
## 0.2.163
## 0.2.162
## 0.2.161
+1 -1
View File
@@ -56,5 +56,5 @@
"type": "module",
"types": "./dist/types/exports/thirdweb.d.ts",
"typings": "./dist/types/exports/thirdweb.d.ts",
"version": "0.2.162"
"version": "0.2.163"
}
+1076 -15
View File
File diff suppressed because it is too large Load Diff