diff --git a/packages/transactions/.eslintrc.js b/packages/transactions/.eslintrc.js
new file mode 100644
index 00000000..9b81937b
--- /dev/null
+++ b/packages/transactions/.eslintrc.js
@@ -0,0 +1,17 @@
+/* eslint-env node */
+
+// @ts-check
+
+const { defineConfig } = require("eslint-define-config");
+
+module.exports = defineConfig({
+ extends: ["../../.eslintrc.js"],
+ overrides: [
+ {
+ files: ["tsup.config.ts"],
+ rules: {
+ "import/no-extraneous-dependencies": "off",
+ },
+ },
+ ],
+});
\ No newline at end of file
diff --git a/packages/transactions/README.md b/packages/transactions/README.md
new file mode 100644
index 00000000..be1e669e
--- /dev/null
+++ b/packages/transactions/README.md
@@ -0,0 +1,353 @@
+# @phantom/transactions
+
+A multi-chain transaction builder package that simplifies transaction creation for dApp development with Phantom Wallet SDK. Build transactions for Solana, Ethereum, and other blockchains with a unified API.
+
+## Installation
+
+```bash
+npm install @phantom/transactions
+# or
+yarn add @phantom/transactions
+```
+
+## Overview
+
+The `@phantom/transactions` package provides a simple, unified interface for creating transactions across multiple blockchains. It automatically handles chain-specific logic while providing a consistent developer experience.
+
+### Supported Networks
+
+- **Solana**: Native SOL transfers and SPL tokens
+- **Ethereum/EVM**: Native ETH transfers and ERC-20 tokens
+ - Ethereum, Polygon, Arbitrum, Optimism, Base, BSC, Avalanche
+- **Bitcoin**: Native BTC transfers (coming soon)
+- **Sui**: Native SUI transfers and tokens (coming soon)
+
+## Quick Start
+
+```typescript
+import { createSendTokenTransaction } from "@phantom/transactions";
+import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
+
+function SendToken() {
+ const { signAndSendTransaction } = useSignAndSendTransaction();
+
+ const handleSend = async () => {
+ // Create transaction
+ const { transaction, error } = await createSendTokenTransaction({
+ networkId: NetworkId.SOLANA_MAINNET,
+ from: "sender-address",
+ to: "recipient-address",
+ amount: "1.5", // 1.5 SOL
+ });
+
+ if (error) {
+ console.error("Transaction creation failed:", error);
+ return;
+ }
+
+ // Sign and send with Phantom SDK
+ const signature = await signAndSendTransaction({
+ transaction,
+ networkId: NetworkId.SOLANA_MAINNET,
+ });
+ };
+
+ return ;
+}
+```
+
+## API Reference
+
+### createSendTokenTransaction(params)
+
+Creates a transaction for sending tokens on any supported blockchain.
+
+**Parameters:**
+- `networkId` (NetworkId) - The target network identifier
+- `from` (string) - Sender address
+- `to` (string) - Recipient address
+- `amount` (string | number | bigint) - Amount to send
+- `token?` (string) - Token contract address (optional for native transfers)
+- `decimals?` (number) - Token decimals (auto-detected if not provided)
+
+**Returns:**
+- `Promise` with:
+ - `transaction` - The blockchain-specific transaction object
+ - `error?` - Error message if transaction creation failed
+
+## Usage Examples
+
+### Native Token Transfers
+
+```typescript
+import { createSendTokenTransaction, NetworkId } from "@phantom/transactions";
+
+// Send SOL on Solana
+const { transaction, error } = await createSendTokenTransaction({
+ networkId: NetworkId.SOLANA_MAINNET,
+ from: "sender-solana-address",
+ to: "recipient-solana-address",
+ amount: "0.1", // 0.1 SOL
+});
+
+// Send ETH on Ethereum
+const { transaction, error } = await createSendTokenTransaction({
+ networkId: NetworkId.ETHEREUM_MAINNET,
+ from: "0x...", // sender address
+ to: "0x...", // recipient address
+ amount: "0.05", // 0.05 ETH
+});
+
+// Send MATIC on Polygon
+const { transaction, error } = await createSendTokenTransaction({
+ networkId: NetworkId.POLYGON_MAINNET,
+ from: "0x...",
+ to: "0x...",
+ amount: "10", // 10 MATIC
+});
+```
+
+### Token Transfers
+
+```typescript
+// Send USDC on Solana (SPL Token)
+const { transaction, error } = await createSendTokenTransaction({
+ networkId: NetworkId.SOLANA_MAINNET,
+ from: "sender-address",
+ to: "recipient-address",
+ amount: "100", // 100 USDC
+ token: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v", // USDC mint address
+ decimals: 6, // USDC has 6 decimals
+});
+
+// Send USDC on Ethereum (ERC-20)
+const { transaction, error } = await createSendTokenTransaction({
+ networkId: NetworkId.ETHEREUM_MAINNET,
+ from: "0x...",
+ to: "0x...",
+ amount: "50",
+ token: "0xA0b86a33E6441E52bB62c678b9431B57e4FB3b3A", // USDC contract address
+ decimals: 6,
+});
+```
+
+### Convenience Functions
+
+```typescript
+import { createNativeTransfer, createTokenTransfer } from "@phantom/transactions";
+
+// Native transfer (convenience function)
+const { transaction } = await createNativeTransfer({
+ networkId: NetworkId.SOLANA_DEVNET,
+ from: "sender",
+ to: "recipient",
+ amount: "2.0",
+});
+
+// Token transfer (convenience function)
+const { transaction } = await createTokenTransfer({
+ networkId: NetworkId.ETHEREUM_MAINNET,
+ from: "0x...",
+ to: "0x...",
+ amount: "1000",
+ token: "0x...", // Required for token transfers
+ decimals: 18,
+});
+```
+
+## RPC Configuration
+
+Configure custom RPC endpoints for different networks:
+
+```typescript
+import { setRPCConfig, getRPCConfig } from "@phantom/transactions";
+
+// Set custom RPC endpoints
+setRPCConfig({
+ solana: {
+ mainnet: "https://your-solana-rpc.com",
+ devnet: "https://your-solana-devnet.com",
+ },
+ ethereum: {
+ mainnet: "https://your-ethereum-rpc.com",
+ sepolia: "https://your-sepolia-rpc.com",
+ },
+ polygon: {
+ mainnet: "https://your-polygon-rpc.com",
+ },
+});
+
+// Get current configuration
+const config = getRPCConfig();
+console.log(config.solana?.mainnet);
+```
+
+### Environment Variables
+
+You can also configure RPC endpoints via environment variables:
+
+```bash
+# Solana
+SOLANA_MAINNET_RPC=https://api.mainnet-beta.solana.com
+SOLANA_DEVNET_RPC=https://api.devnet.solana.com
+
+# Ethereum
+ETHEREUM_MAINNET_RPC=https://mainnet.infura.io/v3/YOUR_KEY
+ETHEREUM_SEPOLIA_RPC=https://sepolia.infura.io/v3/YOUR_KEY
+
+# Polygon
+POLYGON_MAINNET_RPC=https://polygon-mainnet.infura.io/v3/YOUR_KEY
+
+# Other networks...
+```
+
+## Integration with Phantom SDKs
+
+### React SDK Integration
+
+```typescript
+import { createSendTokenTransaction } from "@phantom/transactions";
+import { useSignAndSendTransaction, NetworkId } from "@phantom/react-sdk";
+
+function TokenSender() {
+ const { signAndSendTransaction, loading } = useSignAndSendTransaction();
+
+ const sendUSDC = async () => {
+ const { transaction, error } = await createSendTokenTransaction({
+ networkId: NetworkId.SOLANA_MAINNET,
+ from: "your-address",
+ to: "recipient-address",
+ amount: "10",
+ token: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
+ });
+
+ if (error) {
+ alert(error);
+ return;
+ }
+
+ try {
+ const signature = await signAndSendTransaction({
+ transaction,
+ networkId: NetworkId.SOLANA_MAINNET,
+ });
+ console.log("Transaction sent:", signature);
+ } catch (err) {
+ console.error("Failed to send:", err);
+ }
+ };
+
+ return (
+
+ );
+}
+```
+
+### Server SDK Integration
+
+```typescript
+import { createSendTokenTransaction } from "@phantom/transactions";
+import { ServerSDK, NetworkId } from "@phantom/server-sdk";
+
+const sdk = new ServerSDK({
+ organizationId: process.env.ORGANIZATION_ID!,
+ apiPrivateKey: process.env.PRIVATE_KEY!,
+ apiBaseUrl: process.env.API_URL!,
+});
+
+async function serverSideTransfer(walletId: string) {
+ // Create transaction
+ const { transaction, error } = await createSendTokenTransaction({
+ networkId: NetworkId.ETHEREUM_MAINNET,
+ from: "wallet-address",
+ to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
+ amount: "0.1", // 0.1 ETH
+ });
+
+ if (error) {
+ throw new Error(error);
+ }
+
+ // Sign and send with server SDK
+ const result = await sdk.signAndSendTransaction({
+ walletId,
+ transaction,
+ networkId: NetworkId.ETHEREUM_MAINNET,
+ });
+
+ return result;
+}
+```
+
+## Error Handling
+
+```typescript
+const { transaction, error } = await createSendTokenTransaction({
+ networkId: NetworkId.SOLANA_MAINNET,
+ from: "invalid-address",
+ to: "recipient",
+ amount: "1.0",
+});
+
+if (error) {
+ console.error("Transaction creation failed:", error);
+ // Handle specific error cases
+ if (error.includes("Invalid address")) {
+ // Handle invalid address
+ } else if (error.includes("Insufficient")) {
+ // Handle insufficient balance
+ }
+ return;
+}
+
+// Transaction created successfully
+console.log("Transaction ready:", transaction);
+```
+
+## Network Support
+
+| Network | Native Token | Custom Tokens | Status |
+|---------|-------------|---------------|---------|
+| Solana | ✅ SOL | 🚧 SPL Tokens | Partial |
+| Ethereum | ✅ ETH | 🚧 ERC-20 | Partial |
+| Polygon | ✅ MATIC | 🚧 ERC-20 | Partial |
+| Arbitrum | ✅ ETH | 🚧 ERC-20 | Partial |
+| Optimism | ✅ ETH | 🚧 ERC-20 | Partial |
+| Base | ✅ ETH | 🚧 ERC-20 | Partial |
+| BSC | ✅ BNB | 🚧 BEP-20 | Partial |
+| Avalanche | ✅ AVAX | 🚧 ERC-20 | Partial |
+| Bitcoin | 🚧 BTC | ❌ | Coming Soon |
+| Sui | 🚧 SUI | 🚧 Sui Tokens | Coming Soon |
+
+## Development Status
+
+This package is in active development. Current limitations:
+
+- **SPL Token transfers**: Need @solana/spl-token implementation
+- **ERC-20 transfers**: Need proper contract call encoding
+- **Bitcoin**: Full implementation needed
+- **Sui tokens**: Token-specific logic needed
+
+## Contributing
+
+This package is part of the Phantom Wallet SDK monorepo. Contributions are welcome!
+
+```bash
+# Install dependencies
+yarn install
+
+# Build the package
+yarn workspace @phantom/transactions build
+
+# Run tests
+yarn workspace @phantom/transactions test
+
+# Lint code
+yarn workspace @phantom/transactions lint
+```
+
+## License
+
+MIT License - see LICENSE file for details.
\ No newline at end of file
diff --git a/packages/transactions/jest.config.js b/packages/transactions/jest.config.js
new file mode 100644
index 00000000..6bde9e0b
--- /dev/null
+++ b/packages/transactions/jest.config.js
@@ -0,0 +1,19 @@
+/** @type {import('jest').Config} */
+module.exports = {
+ preset: 'ts-jest',
+ testEnvironment: 'node',
+ roots: ['/src'],
+ testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
+ transform: {
+ '^.+\\.ts$': 'ts-jest',
+ },
+ collectCoverageFrom: [
+ 'src/**/*.ts',
+ '!src/**/*.d.ts',
+ '!src/**/*.test.ts',
+ ],
+ moduleNameMapping: {
+ '^@phantom/(.*)$': '/../$1/src',
+ },
+ testTimeout: 10000,
+};
\ No newline at end of file
diff --git a/packages/transactions/package.json b/packages/transactions/package.json
new file mode 100644
index 00000000..9bb964ee
--- /dev/null
+++ b/packages/transactions/package.json
@@ -0,0 +1,64 @@
+{
+ "name": "@phantom/transactions",
+ "version": "0.0.1",
+ "description": "Transaction builders for multi-chain dApp development with Phantom Wallet SDK",
+ "main": "dist/index.js",
+ "module": "dist/index.mjs",
+ "types": "dist/index.d.ts",
+ "exports": {
+ ".": {
+ "import": "./dist/index.mjs",
+ "require": "./dist/index.js",
+ "types": "./dist/index.d.ts"
+ }
+ },
+ "files": [
+ "dist"
+ ],
+ "scripts": {
+ "?pack-release": "When https://github.com/changesets/changesets/issues/432 has a solution we can remove this trick",
+ "pack-release": "rimraf ./_release && yarn pack && mkdir ./_release && tar zxvf ./package.tgz --directory ./_release && rm ./package.tgz",
+ "build": "rimraf ./dist && tsup",
+ "dev": "rimraf ./dist && tsup --watch",
+ "clean": "rm -rf dist",
+ "test": "jest",
+ "test:watch": "jest --watch",
+ "lint": "tsc --noEmit && eslint --cache . --ext .ts",
+ "prettier": "prettier --write \"src/**/*.{ts}\""
+ },
+ "dependencies": {
+ "@mysten/sui.js": "^0.54.1",
+ "@phantom/client": "workspace:^",
+ "@solana/web3.js": "^1.87.6",
+ "bitcoinjs-lib": "^6.1.5",
+ "buffer": "^6.0.3",
+ "viem": "^2.21.1"
+ },
+ "devDependencies": {
+ "@types/jest": "^29.5.12",
+ "@types/node": "^20.11.0",
+ "eslint": "8.53.0",
+ "jest": "^29.7.0",
+ "prettier": "^3.5.2",
+ "rimraf": "^6.0.1",
+ "ts-jest": "^29.1.2",
+ "tsup": "^6.7.0",
+ "typescript": "^5.0.4"
+ },
+ "keywords": [
+ "phantom",
+ "transactions",
+ "solana",
+ "ethereum",
+ "bitcoin",
+ "sui",
+ "web3",
+ "dapp",
+ "blockchain",
+ "multi-chain"
+ ],
+ "license": "MIT",
+ "publishConfig": {
+ "directory": "_release/package"
+ }
+}
diff --git a/packages/transactions/src/builders/bitcoin.ts b/packages/transactions/src/builders/bitcoin.ts
new file mode 100644
index 00000000..70aa97ec
--- /dev/null
+++ b/packages/transactions/src/builders/bitcoin.ts
@@ -0,0 +1,33 @@
+import type { BitcoinTransactionBuilder, SendTokenTransactionParams, TransactionResult } from "../types";
+import { getRPCUrl } from "../config";
+
+export class BitcoinTransactionBuilderImpl implements BitcoinTransactionBuilder {
+ async createSendTokenTransaction(params: SendTokenTransactionParams): Promise {
+ try {
+ const rpcUrl = getRPCUrl(params.networkId);
+
+ // This is a placeholder implementation
+ // In a real implementation, you would:
+ // 1. Use bitcoinjs-lib to create transactions
+ // 2. Fetch UTXOs from the Bitcoin network
+ // 3. Calculate fees
+ // 4. Create and sign the transaction
+
+ // Bitcoin doesn't have native token support, but you could handle:
+ // - Native BTC transfers
+ // - Lightning Network payments
+ // - Ordinals/Inscriptions
+ // - BRC-20 tokens (via Ordinals)
+
+ return {
+ transaction: null,
+ error: "Bitcoin transaction creation not yet implemented. Please add bitcoinjs-lib implementation.",
+ };
+ } catch (error: any) {
+ return {
+ transaction: null,
+ error: `Failed to create Bitcoin transaction: ${error.message}`,
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/transactions/src/builders/evm.ts b/packages/transactions/src/builders/evm.ts
new file mode 100644
index 00000000..5a8c7ebe
--- /dev/null
+++ b/packages/transactions/src/builders/evm.ts
@@ -0,0 +1,149 @@
+import { createPublicClient, http, parseEther, parseUnits, formatUnits, getContract } from "viem";
+import { mainnet, sepolia, polygon, polygonMumbai, arbitrum, arbitrumSepolia, optimism, optimismSepolia, base, baseSepolia, bsc, bscTestnet, avalanche, avalancheFuji } from "viem/chains";
+import type { EVMTransactionBuilder, SendTokenTransactionParams, TransactionResult } from "../types";
+import { getRPCUrl } from "../config";
+
+// ERC-20 ABI for token transfers
+const ERC20_ABI = [
+ {
+ constant: true,
+ inputs: [],
+ name: "decimals",
+ outputs: [{ name: "", type: "uint8" }],
+ type: "function",
+ },
+ {
+ constant: false,
+ inputs: [
+ { name: "to", type: "address" },
+ { name: "value", type: "uint256" },
+ ],
+ name: "transfer",
+ outputs: [{ name: "", type: "bool" }],
+ type: "function",
+ },
+] as const;
+
+export class EVMTransactionBuilderImpl implements EVMTransactionBuilder {
+ private getChain(networkId: string) {
+ const [, network] = networkId.toLowerCase().split(':');
+
+ switch (network) {
+ case '1': return mainnet;
+ case '11155111': return sepolia;
+ case '5': return sepolia; // Goerli deprecated, fallback to Sepolia
+ case '137': return polygon;
+ case '80001': return polygonMumbai;
+ case '42161': return arbitrum;
+ case '421614': return arbitrumSepolia;
+ case '10': return optimism;
+ case '11155420': return optimismSepolia;
+ case '8453': return base;
+ case '84532': return baseSepolia;
+ case '56': return bsc;
+ case '97': return bscTestnet;
+ case '43114': return avalanche;
+ case '43113': return avalancheFuji;
+ default: return mainnet;
+ }
+ }
+
+ private getPublicClient(networkId: string) {
+ const chain = this.getChain(networkId);
+ const rpcUrl = getRPCUrl(networkId);
+
+ return createPublicClient({
+ chain,
+ transport: http(rpcUrl),
+ });
+ }
+
+ async createSendTokenTransaction(params: SendTokenTransactionParams): Promise {
+ try {
+ const publicClient = this.getPublicClient(params.networkId);
+
+ // Handle native token transfer (ETH, MATIC, etc.)
+ if (!params.token) {
+ return this.createNativeTransfer(params);
+ }
+
+ // Handle ERC-20 token transfer
+ return await this.createERC20Transfer(publicClient, params);
+ } catch (error: any) {
+ return {
+ transaction: null,
+ error: `Failed to create EVM transaction: ${error.message}`,
+ };
+ }
+ }
+
+ private createNativeTransfer(params: SendTokenTransactionParams): TransactionResult {
+ try {
+ // Convert amount to wei
+ const value = typeof params.amount === 'string'
+ ? parseEther(params.amount)
+ : typeof params.amount === 'bigint'
+ ? params.amount
+ : parseEther(params.amount.toString());
+
+ const transaction = {
+ to: params.to as `0x${string}`,
+ value,
+ // Gas limit and gas price will be estimated by the wallet
+ };
+
+ return {
+ transaction,
+ };
+ } catch (error: any) {
+ return {
+ transaction: null,
+ error: `Failed to create native transfer: ${error.message}`,
+ };
+ }
+ }
+
+ private async createERC20Transfer(publicClient: any, params: SendTokenTransactionParams): Promise {
+ try {
+ const tokenContract = getContract({
+ address: params.token as `0x${string}`,
+ abi: ERC20_ABI,
+ client: publicClient,
+ });
+
+ // Get token decimals if not provided
+ let decimals = params.decimals;
+ if (!decimals) {
+ try {
+ decimals = await tokenContract.read.decimals();
+ } catch (error) {
+ decimals = 18; // Default to 18 decimals
+ }
+ }
+
+ // Convert amount to token units
+ const value = typeof params.amount === 'string'
+ ? parseUnits(params.amount, decimals)
+ : typeof params.amount === 'bigint'
+ ? params.amount
+ : parseUnits(params.amount.toString(), decimals);
+
+ // Create transfer transaction data
+ const transaction = {
+ to: params.token as `0x${string}`,
+ data: tokenContract.write.transfer.toString(), // This needs proper encoding
+ // Note: This is a simplified version. In practice, you'd need to properly encode the function call
+ };
+
+ return {
+ transaction: null,
+ error: "ERC-20 token transfers need proper function encoding. Please implement contract call encoding.",
+ };
+ } catch (error: any) {
+ return {
+ transaction: null,
+ error: `Failed to create ERC-20 transfer: ${error.message}`,
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/transactions/src/builders/solana.ts b/packages/transactions/src/builders/solana.ts
new file mode 100644
index 00000000..d5c6406d
--- /dev/null
+++ b/packages/transactions/src/builders/solana.ts
@@ -0,0 +1,97 @@
+import { Connection, PublicKey, Transaction, SystemProgram, LAMPORTS_PER_SOL } from "@solana/web3.js";
+import type { SolanaTransactionBuilder, SendTokenTransactionParams, TransactionResult } from "../types";
+import { getRPCUrl } from "../config";
+
+export class SolanaTransactionBuilderImpl implements SolanaTransactionBuilder {
+ private getConnection(networkId: string): Connection {
+ const rpcUrl = getRPCUrl(networkId);
+ return new Connection(rpcUrl, 'confirmed');
+ }
+
+ async createSendTokenTransaction(params: SendTokenTransactionParams): Promise {
+ try {
+ const connection = this.getConnection(params.networkId);
+ const fromPubkey = new PublicKey(params.from);
+ const toPubkey = new PublicKey(params.to);
+
+ // Handle native SOL transfer
+ if (!params.token) {
+ return this.createNativeSOLTransfer(connection, fromPubkey, toPubkey, params.amount);
+ }
+
+ // Handle SPL token transfer
+ return this.createSPLTokenTransfer(connection, fromPubkey, toPubkey, params.token, params.amount, params.decimals);
+ } catch (error: any) {
+ return {
+ transaction: null,
+ error: `Failed to create Solana transaction: ${error.message}`,
+ };
+ }
+ }
+
+ private async createNativeSOLTransfer(
+ connection: Connection,
+ fromPubkey: PublicKey,
+ toPubkey: PublicKey,
+ amount: string | number | bigint
+ ): Promise {
+ try {
+ // Convert amount to lamports
+ const lamports = typeof amount === 'string'
+ ? Math.floor(parseFloat(amount) * LAMPORTS_PER_SOL)
+ : typeof amount === 'bigint'
+ ? Number(amount)
+ : Math.floor(amount * LAMPORTS_PER_SOL);
+
+ const transaction = new Transaction().add(
+ SystemProgram.transfer({
+ fromPubkey,
+ toPubkey,
+ lamports,
+ })
+ );
+
+ // Get recent blockhash
+ const { blockhash } = await connection.getLatestBlockhash();
+ transaction.recentBlockhash = blockhash;
+ transaction.feePayer = fromPubkey;
+
+ return {
+ transaction,
+ };
+ } catch (error: any) {
+ return {
+ transaction: null,
+ error: `Failed to create native SOL transfer: ${error.message}`,
+ };
+ }
+ }
+
+ private async createSPLTokenTransfer(
+ connection: Connection,
+ fromPubkey: PublicKey,
+ toPubkey: PublicKey,
+ tokenAddress: string,
+ amount: string | number | bigint,
+ decimals?: number
+ ): Promise {
+ try {
+ // This is a placeholder for SPL token transfer
+ // In a real implementation, you would:
+ // 1. Import @solana/spl-token
+ // 2. Get or create associated token accounts
+ // 3. Create transfer instruction
+ // 4. Handle token decimals properly
+
+ return {
+ transaction: null,
+ error: "SPL token transfers not yet implemented. Please add @solana/spl-token dependency and implement token transfer logic.",
+ };
+ } catch (error: any) {
+ return {
+ transaction: null,
+ error: `Failed to create SPL token transfer: ${error.message}`,
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/transactions/src/builders/sui.ts b/packages/transactions/src/builders/sui.ts
new file mode 100644
index 00000000..29f35b44
--- /dev/null
+++ b/packages/transactions/src/builders/sui.ts
@@ -0,0 +1,76 @@
+import { SuiClient, getFullnodeUrl } from "@mysten/sui.js/client";
+import { TransactionBlock } from "@mysten/sui.js/transactions";
+import type { SuiTransactionBuilder, SendTokenTransactionParams, TransactionResult } from "../types";
+import { getRPCUrl } from "../config";
+
+export class SuiTransactionBuilderImpl implements SuiTransactionBuilder {
+ private getSuiClient(networkId: string): SuiClient {
+ const rpcUrl = getRPCUrl(networkId);
+ return new SuiClient({ url: rpcUrl });
+ }
+
+ async createSendTokenTransaction(params: SendTokenTransactionParams): Promise {
+ try {
+ const client = this.getSuiClient(params.networkId);
+
+ // Handle native SUI transfer
+ if (!params.token) {
+ return this.createNativeSuiTransfer(params);
+ }
+
+ // Handle Sui token transfer
+ return this.createSuiTokenTransfer(client, params);
+ } catch (error: any) {
+ return {
+ transaction: null,
+ error: `Failed to create Sui transaction: ${error.message}`,
+ };
+ }
+ }
+
+ private createNativeSuiTransfer(params: SendTokenTransactionParams): TransactionResult {
+ try {
+ const tx = new TransactionBlock();
+
+ // Convert amount to MIST (1 SUI = 1,000,000,000 MIST)
+ const amount = typeof params.amount === 'string'
+ ? Math.floor(parseFloat(params.amount) * 1_000_000_000)
+ : typeof params.amount === 'bigint'
+ ? Number(params.amount)
+ : Math.floor(params.amount * 1_000_000_000);
+
+ // Split coins and transfer
+ const [coin] = tx.splitCoins(tx.gas, [tx.pure(amount)]);
+ tx.transferObjects([coin], tx.pure(params.to));
+
+ return {
+ transaction: tx,
+ };
+ } catch (error: any) {
+ return {
+ transaction: null,
+ error: `Failed to create native SUI transfer: ${error.message}`,
+ };
+ }
+ }
+
+ private async createSuiTokenTransfer(client: SuiClient, params: SendTokenTransactionParams): Promise {
+ try {
+ // This is a placeholder for Sui token transfers
+ // In a real implementation, you would:
+ // 1. Query for coin objects of the specified type
+ // 2. Create appropriate transfer transactions
+ // 3. Handle token-specific logic
+
+ return {
+ transaction: null,
+ error: "Sui token transfers not yet fully implemented. Please add token-specific logic.",
+ };
+ } catch (error: any) {
+ return {
+ transaction: null,
+ error: `Failed to create Sui token transfer: ${error.message}`,
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages/transactions/src/config.ts b/packages/transactions/src/config.ts
new file mode 100644
index 00000000..06a8e9b8
--- /dev/null
+++ b/packages/transactions/src/config.ts
@@ -0,0 +1,128 @@
+import type { RPCConfig } from "./types";
+
+// Safe environment variable access for isomorphic support
+const getEnvVar = (name: string): string | undefined => {
+ if (typeof process !== 'undefined' && process.env) {
+ return process.env[name];
+ }
+ return undefined;
+};
+
+// Default RPC endpoints - can be overridden via environment variables or config
+const DEFAULT_RPC_CONFIG: RPCConfig = {
+ solana: {
+ mainnet: getEnvVar('SOLANA_MAINNET_RPC') || "https://api.mainnet-beta.solana.com",
+ devnet: getEnvVar('SOLANA_DEVNET_RPC') || "https://api.devnet.solana.com",
+ testnet: getEnvVar('SOLANA_TESTNET_RPC') || "https://api.testnet.solana.com",
+ },
+ ethereum: {
+ mainnet: getEnvVar('ETHEREUM_MAINNET_RPC') || "https://mainnet.infura.io/v3/YOUR_INFURA_KEY",
+ sepolia: getEnvVar('ETHEREUM_SEPOLIA_RPC') || "https://sepolia.infura.io/v3/YOUR_INFURA_KEY",
+ goerli: getEnvVar('ETHEREUM_GOERLI_RPC') || "https://goerli.infura.io/v3/YOUR_INFURA_KEY",
+ },
+ polygon: {
+ mainnet: getEnvVar('POLYGON_MAINNET_RPC') || "https://polygon-mainnet.infura.io/v3/YOUR_INFURA_KEY",
+ mumbai: getEnvVar('POLYGON_MUMBAI_RPC') || "https://polygon-mumbai.infura.io/v3/YOUR_INFURA_KEY",
+ },
+ arbitrum: {
+ mainnet: getEnvVar('ARBITRUM_MAINNET_RPC') || "https://arbitrum-mainnet.infura.io/v3/YOUR_INFURA_KEY",
+ sepolia: getEnvVar('ARBITRUM_SEPOLIA_RPC') || "https://arbitrum-sepolia.infura.io/v3/YOUR_INFURA_KEY",
+ },
+ optimism: {
+ mainnet: getEnvVar('OPTIMISM_MAINNET_RPC') || "https://optimism-mainnet.infura.io/v3/YOUR_INFURA_KEY",
+ sepolia: getEnvVar('OPTIMISM_SEPOLIA_RPC') || "https://optimism-sepolia.infura.io/v3/YOUR_INFURA_KEY",
+ },
+ base: {
+ mainnet: getEnvVar('BASE_MAINNET_RPC') || "https://mainnet.base.org",
+ sepolia: getEnvVar('BASE_SEPOLIA_RPC') || "https://sepolia.base.org",
+ },
+ bsc: {
+ mainnet: getEnvVar('BSC_MAINNET_RPC') || "https://bsc-dataseed.binance.org",
+ testnet: getEnvVar('BSC_TESTNET_RPC') || "https://data-seed-prebsc-1-s1.binance.org:8545",
+ },
+ avalanche: {
+ mainnet: getEnvVar('AVALANCHE_MAINNET_RPC') || "https://api.avax.network/ext/bc/C/rpc",
+ fuji: getEnvVar('AVALANCHE_FUJI_RPC') || "https://api.avax-test.network/ext/bc/C/rpc",
+ },
+ bitcoin: {
+ mainnet: getEnvVar('BITCOIN_MAINNET_RPC') || "https://blockstream.info/api",
+ testnet: getEnvVar('BITCOIN_TESTNET_RPC') || "https://blockstream.info/testnet/api",
+ },
+ sui: {
+ mainnet: getEnvVar('SUI_MAINNET_RPC') || "https://fullnode.mainnet.sui.io:443",
+ testnet: getEnvVar('SUI_TESTNET_RPC') || "https://fullnode.testnet.sui.io:443",
+ devnet: getEnvVar('SUI_DEVNET_RPC') || "https://fullnode.devnet.sui.io:443",
+ },
+};
+
+let currentConfig: RPCConfig = { ...DEFAULT_RPC_CONFIG };
+
+export function getRPCConfig(): RPCConfig {
+ return currentConfig;
+}
+
+export function setRPCConfig(config: Partial): void {
+ currentConfig = {
+ ...currentConfig,
+ ...config,
+ // Deep merge for nested objects
+ solana: { ...currentConfig.solana, ...config.solana },
+ ethereum: { ...currentConfig.ethereum, ...config.ethereum },
+ polygon: { ...currentConfig.polygon, ...config.polygon },
+ arbitrum: { ...currentConfig.arbitrum, ...config.arbitrum },
+ optimism: { ...currentConfig.optimism, ...config.optimism },
+ base: { ...currentConfig.base, ...config.base },
+ bsc: { ...currentConfig.bsc, ...config.bsc },
+ avalanche: { ...currentConfig.avalanche, ...config.avalanche },
+ bitcoin: { ...currentConfig.bitcoin, ...config.bitcoin },
+ sui: { ...currentConfig.sui, ...config.sui },
+ };
+}
+
+export function getRPCUrl(networkId: string): string {
+ const config = getRPCConfig();
+ const [chain, network] = networkId.toLowerCase().split(':');
+
+ switch (chain) {
+ case 'solana':
+ return config.solana?.[network as keyof typeof config.solana] || config.solana?.mainnet || DEFAULT_RPC_CONFIG.solana!.mainnet!;
+
+ case 'ethereum':
+ case 'eip155':
+ const ethNetwork = network === '1' ? 'mainnet' : network === '11155111' ? 'sepolia' : network === '5' ? 'goerli' : 'mainnet';
+ return config.ethereum?.[ethNetwork as keyof typeof config.ethereum] || config.ethereum?.mainnet || DEFAULT_RPC_CONFIG.ethereum!.mainnet!;
+
+ case 'polygon':
+ const polygonNetwork = network === '137' ? 'mainnet' : network === '80001' ? 'mumbai' : 'mainnet';
+ return config.polygon?.[polygonNetwork as keyof typeof config.polygon] || config.polygon?.mainnet || DEFAULT_RPC_CONFIG.polygon!.mainnet!;
+
+ case 'arbitrum':
+ const arbitrumNetwork = network === '42161' ? 'mainnet' : network === '421614' ? 'sepolia' : 'mainnet';
+ return config.arbitrum?.[arbitrumNetwork as keyof typeof config.arbitrum] || config.arbitrum?.mainnet || DEFAULT_RPC_CONFIG.arbitrum!.mainnet!;
+
+ case 'optimism':
+ const optimismNetwork = network === '10' ? 'mainnet' : network === '11155420' ? 'sepolia' : 'mainnet';
+ return config.optimism?.[optimismNetwork as keyof typeof config.optimism] || config.optimism?.mainnet || DEFAULT_RPC_CONFIG.optimism!.mainnet!;
+
+ case 'base':
+ const baseNetwork = network === '8453' ? 'mainnet' : network === '84532' ? 'sepolia' : 'mainnet';
+ return config.base?.[baseNetwork as keyof typeof config.base] || config.base?.mainnet || DEFAULT_RPC_CONFIG.base!.mainnet!;
+
+ case 'bsc':
+ const bscNetwork = network === '56' ? 'mainnet' : network === '97' ? 'testnet' : 'mainnet';
+ return config.bsc?.[bscNetwork as keyof typeof config.bsc] || config.bsc?.mainnet || DEFAULT_RPC_CONFIG.bsc!.mainnet!;
+
+ case 'avalanche':
+ const avalancheNetwork = network === '43114' ? 'mainnet' : network === '43113' ? 'fuji' : 'mainnet';
+ return config.avalanche?.[avalancheNetwork as keyof typeof config.avalanche] || config.avalanche?.mainnet || DEFAULT_RPC_CONFIG.avalanche!.mainnet!;
+
+ case 'bitcoin':
+ return config.bitcoin?.[network as keyof typeof config.bitcoin] || config.bitcoin?.mainnet || DEFAULT_RPC_CONFIG.bitcoin!.mainnet!;
+
+ case 'sui':
+ return config.sui?.[network as keyof typeof config.sui] || config.sui?.mainnet || DEFAULT_RPC_CONFIG.sui!.mainnet!;
+
+ default:
+ throw new Error(`Unsupported network: ${networkId}`);
+ }
+}
\ No newline at end of file
diff --git a/packages/transactions/src/index.ts b/packages/transactions/src/index.ts
new file mode 100644
index 00000000..2565838d
--- /dev/null
+++ b/packages/transactions/src/index.ts
@@ -0,0 +1,105 @@
+import type { SendTokenTransactionParams, TransactionResult } from "./types";
+import { SolanaTransactionBuilderImpl } from "./builders/solana";
+import { EVMTransactionBuilderImpl } from "./builders/evm";
+import { BitcoinTransactionBuilderImpl } from "./builders/bitcoin";
+import { SuiTransactionBuilderImpl } from "./builders/sui";
+
+// Export types
+export type * from "./types";
+
+// Export configuration functions
+export { getRPCConfig, setRPCConfig, getRPCUrl } from "./config";
+
+// Builder instances
+const solanaBuilder = new SolanaTransactionBuilderImpl();
+const evmBuilder = new EVMTransactionBuilderImpl();
+const bitcoinBuilder = new BitcoinTransactionBuilderImpl();
+const suiBuilder = new SuiTransactionBuilderImpl();
+
+/**
+ * Create a send token transaction for any supported blockchain
+ *
+ * @param params - Transaction parameters including networkId, addresses, amount, and optional token
+ * @returns Promise - Contains the transaction object or error message
+ *
+ * @example
+ * ```typescript
+ * import { createSendTokenTransaction } from "@phantom/transactions";
+ * import { NetworkId } from "@phantom/client";
+ *
+ * // Native token transfer (SOL, ETH, etc.)
+ * const { transaction, error } = await createSendTokenTransaction({
+ * networkId: NetworkId.SOLANA_MAINNET,
+ * from: "sender-address",
+ * to: "recipient-address",
+ * amount: "1.5", // 1.5 SOL
+ * });
+ *
+ * // Token transfer
+ * const { transaction, error } = await createSendTokenTransaction({
+ * networkId: NetworkId.ETHEREUM_MAINNET,
+ * from: "0x...",
+ * to: "0x...",
+ * amount: "100",
+ * token: "0x...", // USDC contract address
+ * decimals: 6,
+ * });
+ *
+ * if (error) {
+ * console.error("Transaction creation failed:", error);
+ * return;
+ * }
+ *
+ * // Use with Phantom SDK
+ * const signature = await signAndSendTransaction({
+ * transaction,
+ * networkId,
+ * });
+ * ```
+ */
+export async function createSendTokenTransaction(params: SendTokenTransactionParams): Promise {
+ const [chain] = params.networkId.toLowerCase().split(':');
+
+ switch (chain) {
+ case 'solana':
+ return solanaBuilder.createSendTokenTransaction(params);
+
+ case 'ethereum':
+ case 'eip155':
+ case 'polygon':
+ case 'arbitrum':
+ case 'optimism':
+ case 'base':
+ case 'bsc':
+ case 'avalanche':
+ return evmBuilder.createSendTokenTransaction(params);
+
+ case 'bitcoin':
+ return bitcoinBuilder.createSendTokenTransaction(params);
+
+ case 'sui':
+ return suiBuilder.createSendTokenTransaction(params);
+
+ default:
+ return {
+ transaction: null,
+ error: `Unsupported network: ${params.networkId}. Supported networks: Solana, Ethereum/EVM chains, Bitcoin, Sui`,
+ };
+ }
+}
+
+/**
+ * Create a native token transfer (SOL, ETH, BTC, SUI, etc.)
+ * Convenience function for sending native blockchain tokens
+ */
+export async function createNativeTransfer(params: Omit): Promise {
+ return createSendTokenTransaction({ ...params, token: undefined });
+}
+
+/**
+ * Create a token transfer (SPL, ERC-20, etc.)
+ * Convenience function for sending custom tokens
+ */
+export async function createTokenTransfer(params: Required> & SendTokenTransactionParams): Promise {
+ return createSendTokenTransaction(params);
+}
\ No newline at end of file
diff --git a/packages/transactions/src/transactions.test.ts b/packages/transactions/src/transactions.test.ts
new file mode 100644
index 00000000..7bc99980
--- /dev/null
+++ b/packages/transactions/src/transactions.test.ts
@@ -0,0 +1,160 @@
+import { createSendTokenTransaction, createNativeTransfer, setRPCConfig, getRPCConfig } from "./index";
+
+// Mock NetworkId for testing
+const mockNetworkIds = {
+ SOLANA_MAINNET: "solana:mainnet-beta",
+ ETHEREUM_MAINNET: "ethereum:1",
+ POLYGON_MAINNET: "polygon:137",
+ BITCOIN_MAINNET: "bitcoin:mainnet",
+ SUI_MAINNET: "sui:mainnet",
+} as const;
+
+describe("@phantom/transactions", () => {
+ describe("RPC Configuration", () => {
+ it("should have default RPC configuration", () => {
+ const config = getRPCConfig();
+ expect(config.solana?.mainnet).toBeDefined();
+ expect(config.ethereum?.mainnet).toBeDefined();
+ expect(config.polygon?.mainnet).toBeDefined();
+ expect(config.bitcoin?.mainnet).toBeDefined();
+ expect(config.sui?.mainnet).toBeDefined();
+ });
+
+ it("should allow updating RPC configuration", () => {
+ const customRPC = "https://custom-rpc.example.com";
+
+ setRPCConfig({
+ solana: {
+ mainnet: customRPC,
+ },
+ });
+
+ const config = getRPCConfig();
+ expect(config.solana?.mainnet).toBe(customRPC);
+ });
+ });
+
+ describe("createSendTokenTransaction", () => {
+ it("should return error for unsupported network", async () => {
+ const result = await createSendTokenTransaction({
+ networkId: "unsupported:network" as any,
+ from: "test-from",
+ to: "test-to",
+ amount: "1.0",
+ });
+
+ expect(result.transaction).toBeNull();
+ expect(result.error).toContain("Unsupported network");
+ });
+
+ it("should create Solana native transfer", async () => {
+ // Use a custom RPC for testing to avoid hitting real endpoints
+ setRPCConfig({
+ solana: {
+ mainnet: "https://localhost:8899", // Local test RPC that doesn't exist
+ },
+ });
+
+ const result = await createSendTokenTransaction({
+ networkId: mockNetworkIds.SOLANA_MAINNET,
+ from: "11111111111111111111111111111112", // Valid Solana address format
+ to: "11111111111111111111111111111113",
+ amount: "1.0",
+ });
+
+ // Since we don't have real RPC connection in tests, we expect an error
+ // but it should be a connection error, not a parsing error
+ expect(result.error).toBeDefined();
+ expect(result.error).not.toContain("Unsupported network");
+ expect(result.error).toContain("Failed to create Solana transaction");
+ }, 15000);
+
+ it("should handle EVM networks", async () => {
+ const result = await createSendTokenTransaction({
+ networkId: mockNetworkIds.ETHEREUM_MAINNET,
+ from: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
+ to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
+ amount: "0.1",
+ });
+
+ // EVM native transfers should work without RPC connection
+ expect(result.transaction).toBeDefined();
+ expect(result.transaction.to).toBe("0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E");
+ expect(result.transaction.value).toBeDefined();
+ });
+
+ it("should return error for Bitcoin (not implemented)", async () => {
+ const result = await createSendTokenTransaction({
+ networkId: mockNetworkIds.BITCOIN_MAINNET,
+ from: "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
+ to: "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4",
+ amount: "0.001",
+ });
+
+ expect(result.transaction).toBeNull();
+ expect(result.error).toContain("not yet implemented");
+ });
+
+ it("should return error for Sui (partially implemented)", async () => {
+ const result = await createSendTokenTransaction({
+ networkId: mockNetworkIds.SUI_MAINNET,
+ from: "0x123",
+ to: "0x456",
+ amount: "1.0",
+ });
+
+ // Sui native transfers should create a transaction
+ expect(result.transaction).toBeDefined();
+ expect(result.error).toBeUndefined();
+ });
+ });
+
+ describe("createNativeTransfer", () => {
+ it("should create native transfer without token parameter", async () => {
+ const result = await createNativeTransfer({
+ networkId: mockNetworkIds.ETHEREUM_MAINNET,
+ from: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
+ to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
+ amount: "0.5",
+ });
+
+ expect(result.transaction).toBeDefined();
+ expect(result.error).toBeUndefined();
+ });
+ });
+
+ describe("Amount handling", () => {
+ it("should handle string amounts", async () => {
+ const result = await createSendTokenTransaction({
+ networkId: mockNetworkIds.ETHEREUM_MAINNET,
+ from: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
+ to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
+ amount: "1.5", // string
+ });
+
+ expect(result.transaction).toBeDefined();
+ });
+
+ it("should handle number amounts", async () => {
+ const result = await createSendTokenTransaction({
+ networkId: mockNetworkIds.ETHEREUM_MAINNET,
+ from: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
+ to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
+ amount: 2.5, // number
+ });
+
+ expect(result.transaction).toBeDefined();
+ });
+
+ it("should handle bigint amounts", async () => {
+ const result = await createSendTokenTransaction({
+ networkId: mockNetworkIds.ETHEREUM_MAINNET,
+ from: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
+ to: "0x742d35Cc6634C0532925a3b8D4C8db86fB5C4A7E",
+ amount: 1000000000000000000n, // 1 ETH in wei
+ });
+
+ expect(result.transaction).toBeDefined();
+ });
+ });
+});
\ No newline at end of file
diff --git a/packages/transactions/src/types.ts b/packages/transactions/src/types.ts
new file mode 100644
index 00000000..3ef5d6a2
--- /dev/null
+++ b/packages/transactions/src/types.ts
@@ -0,0 +1,79 @@
+import type { NetworkId } from "@phantom/client";
+
+// Base transaction parameters
+export interface BaseTransactionParams {
+ networkId: NetworkId;
+ from: string;
+ to: string;
+ amount: string | number | bigint;
+}
+
+// Send token transaction parameters
+export interface SendTokenTransactionParams extends BaseTransactionParams {
+ token?: string; // Token address (optional for native token transfers)
+ decimals?: number; // Token decimals (auto-detected if not provided)
+}
+
+// Transaction result
+export interface TransactionResult {
+ transaction: any; // The blockchain-specific transaction object
+ error?: string;
+}
+
+// RPC configuration
+export interface RPCConfig {
+ solana?: {
+ mainnet?: string;
+ devnet?: string;
+ testnet?: string;
+ };
+ ethereum?: {
+ mainnet?: string;
+ sepolia?: string;
+ goerli?: string;
+ };
+ polygon?: {
+ mainnet?: string;
+ mumbai?: string;
+ };
+ arbitrum?: {
+ mainnet?: string;
+ sepolia?: string;
+ };
+ optimism?: {
+ mainnet?: string;
+ sepolia?: string;
+ };
+ base?: {
+ mainnet?: string;
+ sepolia?: string;
+ };
+ bsc?: {
+ mainnet?: string;
+ testnet?: string;
+ };
+ avalanche?: {
+ mainnet?: string;
+ fuji?: string;
+ };
+ bitcoin?: {
+ mainnet?: string;
+ testnet?: string;
+ };
+ sui?: {
+ mainnet?: string;
+ testnet?: string;
+ devnet?: string;
+ };
+}
+
+// Transaction builder interface
+export interface TransactionBuilder {
+ createSendTokenTransaction(params: SendTokenTransactionParams): Promise;
+}
+
+// Chain-specific transaction builders
+export interface SolanaTransactionBuilder extends TransactionBuilder {}
+export interface EVMTransactionBuilder extends TransactionBuilder {}
+export interface BitcoinTransactionBuilder extends TransactionBuilder {}
+export interface SuiTransactionBuilder extends TransactionBuilder {}
\ No newline at end of file
diff --git a/packages/transactions/tsconfig.json b/packages/transactions/tsconfig.json
new file mode 100644
index 00000000..3b539eef
--- /dev/null
+++ b/packages/transactions/tsconfig.json
@@ -0,0 +1,11 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "outDir": "./dist",
+ "rootDir": "./src",
+ "types": ["jest", "node"],
+ "moduleResolution": "node"
+ },
+ "include": ["src/**/*"],
+ "exclude": ["dist", "node_modules"]
+}
\ No newline at end of file
diff --git a/packages/transactions/tsup.config.ts b/packages/transactions/tsup.config.ts
new file mode 100644
index 00000000..b8cfe65a
--- /dev/null
+++ b/packages/transactions/tsup.config.ts
@@ -0,0 +1,9 @@
+import { defineConfig } from "tsup";
+
+export default defineConfig({
+ entry: ["src/index.ts"],
+ format: ["cjs", "esm"],
+ dts: true,
+ clean: true,
+ external: ["@phantom/client"],
+});
\ No newline at end of file
diff --git a/yarn.lock b/yarn.lock
index 215f7984..f206ca81 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -5,6 +5,31 @@ __metadata:
version: 8
cacheKey: 10c0
+"@0no-co/graphql.web@npm:^1.0.5":
+ version: 1.2.0
+ resolution: "@0no-co/graphql.web@npm:1.2.0"
+ peerDependencies:
+ graphql: ^14.0.0 || ^15.0.0 || ^16.0.0
+ peerDependenciesMeta:
+ graphql:
+ optional: true
+ checksum: 10c0/4eed600962bfab42afb49cddcfb31a47b00502f59707609cf160559920ce0f5cf8874791e4cafc465ede30ae291992f3f892bc757b2a989e80e50e358f71c518
+ languageName: node
+ linkType: hard
+
+"@0no-co/graphqlsp@npm:^1.12.13":
+ version: 1.15.0
+ resolution: "@0no-co/graphqlsp@npm:1.15.0"
+ dependencies:
+ "@gql.tada/internal": "npm:^1.0.0"
+ graphql: "npm:^15.5.0 || ^16.0.0 || ^17.0.0"
+ peerDependencies:
+ graphql: ^15.5.0 || ^16.0.0 || ^17.0.0
+ typescript: ^5.0.0
+ checksum: 10c0/0805fec594fc7329194a047e9bd0a4e72387268ccf8042ec6b830048f971c48e6a168ad99572e4a5e6d5556b807f3fc1461fcdcc041cdf75ce42e549a6b44108
+ languageName: node
+ linkType: hard
+
"@adraffy/ens-normalize@npm:^1.11.0":
version: 1.11.0
resolution: "@adraffy/ens-normalize@npm:1.11.0"
@@ -1544,6 +1569,49 @@ __metadata:
languageName: node
linkType: hard
+"@gql.tada/cli-utils@npm:1.7.0":
+ version: 1.7.0
+ resolution: "@gql.tada/cli-utils@npm:1.7.0"
+ dependencies:
+ "@0no-co/graphqlsp": "npm:^1.12.13"
+ "@gql.tada/internal": "npm:1.0.8"
+ graphql: "npm:^15.5.0 || ^16.0.0 || ^17.0.0"
+ peerDependencies:
+ "@0no-co/graphqlsp": ^1.12.13
+ "@gql.tada/svelte-support": 1.0.1
+ "@gql.tada/vue-support": 1.0.1
+ graphql: ^15.5.0 || ^16.0.0 || ^17.0.0
+ typescript: ^5.0.0
+ peerDependenciesMeta:
+ "@gql.tada/svelte-support":
+ optional: true
+ "@gql.tada/vue-support":
+ optional: true
+ checksum: 10c0/2e861dcaf153903aaea300dc25025b318caea081ecdcea486170872eeeb64a3a0d3a06b6e1a33e2c6c2ed0efc374bfe819ed74ba8009309db61517eebf405b89
+ languageName: node
+ linkType: hard
+
+"@gql.tada/internal@npm:1.0.8, @gql.tada/internal@npm:^1.0.0":
+ version: 1.0.8
+ resolution: "@gql.tada/internal@npm:1.0.8"
+ dependencies:
+ "@0no-co/graphql.web": "npm:^1.0.5"
+ peerDependencies:
+ graphql: ^15.5.0 || ^16.0.0 || ^17.0.0
+ typescript: ^5.0.0
+ checksum: 10c0/dd9b34296160f7eb4374b1791dd9353fd4147f4d7e2a3a8e2974c2319dc6165a4458c19d9b517a3f7764da4e7a4401c099fdf1936841de02c0e565db95d64a5d
+ languageName: node
+ linkType: hard
+
+"@graphql-typed-document-node/core@npm:^3.2.0":
+ version: 3.2.0
+ resolution: "@graphql-typed-document-node/core@npm:3.2.0"
+ peerDependencies:
+ graphql: ^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0
+ checksum: 10c0/94e9d75c1f178bbae8d874f5a9361708a3350c8def7eaeb6920f2c820e82403b7d4f55b3735856d68e145e86c85cbfe2adc444fdc25519cd51f108697e99346c
+ languageName: node
+ linkType: hard
+
"@humanwhocodes/config-array@npm:^0.11.13":
version: 0.11.14
resolution: "@humanwhocodes/config-array@npm:0.11.14"
@@ -2224,6 +2292,35 @@ __metadata:
languageName: node
linkType: hard
+"@mysten/bcs@npm:0.11.1":
+ version: 0.11.1
+ resolution: "@mysten/bcs@npm:0.11.1"
+ dependencies:
+ bs58: "npm:^5.0.0"
+ checksum: 10c0/aca312c07ef1a2bdfbeef677d1636dfd89b306d0ac04c1c57e5c6386bdea067acbd500d6d50347afe9c87f41fa7c78a6deb3e3bb211a313fbdc7ac2651d33de7
+ languageName: node
+ linkType: hard
+
+"@mysten/sui.js@npm:^0.54.1":
+ version: 0.54.1
+ resolution: "@mysten/sui.js@npm:0.54.1"
+ dependencies:
+ "@graphql-typed-document-node/core": "npm:^3.2.0"
+ "@mysten/bcs": "npm:0.11.1"
+ "@noble/curves": "npm:^1.1.0"
+ "@noble/hashes": "npm:^1.3.1"
+ "@scure/bip32": "npm:^1.3.1"
+ "@scure/bip39": "npm:^1.2.1"
+ "@suchipi/femver": "npm:^1.0.0"
+ bech32: "npm:^2.0.0"
+ gql.tada: "npm:^1.7.0"
+ graphql: "npm:^16.8.1"
+ superstruct: "npm:^1.0.3"
+ tweetnacl: "npm:^1.0.3"
+ checksum: 10c0/3a983b298b0db4eae49448612dcf689ce479912a12c8c65a83eb1d1e66e9a224bc46ca83920d32d255716c11d529c743dff7240257952962bdb0b722e04050db
+ languageName: node
+ linkType: hard
+
"@napi-rs/wasm-runtime@npm:^0.2.11":
version: 0.2.12
resolution: "@napi-rs/wasm-runtime@npm:0.2.12"
@@ -2262,6 +2359,15 @@ __metadata:
languageName: node
linkType: hard
+"@noble/curves@npm:^1.1.0":
+ version: 1.9.6
+ resolution: "@noble/curves@npm:1.9.6"
+ dependencies:
+ "@noble/hashes": "npm:1.8.0"
+ checksum: 10c0/e462875ad752d2cdffc3c7b27b6de3adcff5fae0731e94138bd9e452c5f9b7aaf4c01ea6c62d3c0544b4e7419662535bb2ef1103311de48d51885c053206e118
+ languageName: node
+ linkType: hard
+
"@noble/curves@npm:^1.4.2":
version: 1.9.1
resolution: "@noble/curves@npm:1.9.1"
@@ -2280,7 +2386,7 @@ __metadata:
languageName: node
linkType: hard
-"@noble/hashes@npm:1.8.0, @noble/hashes@npm:^1.4.0, @noble/hashes@npm:^1.8.0, @noble/hashes@npm:~1.8.0":
+"@noble/hashes@npm:1.8.0, @noble/hashes@npm:^1.2.0, @noble/hashes@npm:^1.3.1, @noble/hashes@npm:^1.4.0, @noble/hashes@npm:^1.8.0, @noble/hashes@npm:~1.8.0":
version: 1.8.0
resolution: "@noble/hashes@npm:1.8.0"
checksum: 10c0/06a0b52c81a6fa7f04d67762e08b2c476a00285858150caeaaff4037356dd5e119f45b2a530f638b77a5eeca013168ec1b655db41bae3236cb2e9d511484fc77
@@ -2656,6 +2762,28 @@ __metadata:
languageName: unknown
linkType: soft
+"@phantom/transactions@workspace:packages/transactions":
+ version: 0.0.0-use.local
+ resolution: "@phantom/transactions@workspace:packages/transactions"
+ dependencies:
+ "@mysten/sui.js": "npm:^0.54.1"
+ "@phantom/client": "workspace:^"
+ "@solana/web3.js": "npm:^1.87.6"
+ "@types/jest": "npm:^29.5.12"
+ "@types/node": "npm:^20.11.0"
+ bitcoinjs-lib: "npm:^6.1.5"
+ buffer: "npm:^6.0.3"
+ eslint: "npm:8.53.0"
+ jest: "npm:^29.7.0"
+ prettier: "npm:^3.5.2"
+ rimraf: "npm:^6.0.1"
+ ts-jest: "npm:^29.1.2"
+ tsup: "npm:^6.7.0"
+ typescript: "npm:^5.0.4"
+ viem: "npm:^2.21.1"
+ languageName: unknown
+ linkType: soft
+
"@phantom/wallet-sdk@workspace:*, @phantom/wallet-sdk@workspace:packages/browser-embedded-sdk":
version: 0.0.0-use.local
resolution: "@phantom/wallet-sdk@workspace:packages/browser-embedded-sdk"
@@ -2842,7 +2970,7 @@ __metadata:
languageName: node
linkType: hard
-"@scure/bip32@npm:1.7.0, @scure/bip32@npm:^1.7.0":
+"@scure/bip32@npm:1.7.0, @scure/bip32@npm:^1.3.1, @scure/bip32@npm:^1.7.0":
version: 1.7.0
resolution: "@scure/bip32@npm:1.7.0"
dependencies:
@@ -2853,7 +2981,7 @@ __metadata:
languageName: node
linkType: hard
-"@scure/bip39@npm:1.6.0, @scure/bip39@npm:^1.6.0":
+"@scure/bip39@npm:1.6.0, @scure/bip39@npm:^1.2.1, @scure/bip39@npm:^1.6.0":
version: 1.6.0
resolution: "@scure/bip39@npm:1.6.0"
dependencies:
@@ -3477,6 +3605,13 @@ __metadata:
languageName: node
linkType: hard
+"@suchipi/femver@npm:^1.0.0":
+ version: 1.0.0
+ resolution: "@suchipi/femver@npm:1.0.0"
+ checksum: 10c0/558c15aadeb1153c36e2c00581ba0e04b94ff9a294213e715f377151d66f6ab9704f10f6542230d5e71fdf402d62ee671556dba116ce0ce50876664581942750
+ languageName: node
+ linkType: hard
+
"@swc/helpers@npm:^0.5.11":
version: 0.5.17
resolution: "@swc/helpers@npm:0.5.17"
@@ -4804,6 +4939,13 @@ __metadata:
languageName: node
linkType: hard
+"bech32@npm:^2.0.0":
+ version: 2.0.0
+ resolution: "bech32@npm:2.0.0"
+ checksum: 10c0/45e7cc62758c9b26c05161b4483f40ea534437cf68ef785abadc5b62a2611319b878fef4f86ddc14854f183b645917a19addebc9573ab890e19194bc8f521942
+ languageName: node
+ linkType: hard
+
"better-path-resolve@npm:1.0.0":
version: 1.0.0
resolution: "better-path-resolve@npm:1.0.0"
@@ -4820,6 +4962,27 @@ __metadata:
languageName: node
linkType: hard
+"bip174@npm:^2.1.1":
+ version: 2.1.1
+ resolution: "bip174@npm:2.1.1"
+ checksum: 10c0/d92e142fca85fa4f621dbc9131dafe1da7d69fa7cae03137fa4745d66ffa50561f85ff8c49ca41da8ed1ca65e642415b13dc046531412dfebe6ff03c275e71ae
+ languageName: node
+ linkType: hard
+
+"bitcoinjs-lib@npm:^6.1.5":
+ version: 6.1.7
+ resolution: "bitcoinjs-lib@npm:6.1.7"
+ dependencies:
+ "@noble/hashes": "npm:^1.2.0"
+ bech32: "npm:^2.0.0"
+ bip174: "npm:^2.1.1"
+ bs58check: "npm:^3.0.1"
+ typeforce: "npm:^1.11.3"
+ varuint-bitcoin: "npm:^1.1.2"
+ checksum: 10c0/1ce7415cc967bfc5ea7cba0032e73eaba8e3dd7683dffcc90c020d0dba92de6cf1dc92359733c9efa186a4c3ae9547cc379fa4b4a7fb106c0b126c226dec2a40
+ languageName: node
+ linkType: hard
+
"bn.js@npm:^5.2.0, bn.js@npm:^5.2.1":
version: 5.2.2
resolution: "bn.js@npm:5.2.2"
@@ -4916,6 +5079,16 @@ __metadata:
languageName: node
linkType: hard
+"bs58check@npm:^3.0.1":
+ version: 3.0.1
+ resolution: "bs58check@npm:3.0.1"
+ dependencies:
+ "@noble/hashes": "npm:^1.2.0"
+ bs58: "npm:^5.0.0"
+ checksum: 10c0/a01f62351d17cea5f6607f75f6b4b79d3473d018c52f1dfa6f449751062bb079ebfd556ea81c453de657102ab8c5a6b78620161f21ae05f0e5a43543e0447700
+ languageName: node
+ linkType: hard
+
"bser@npm:2.1.1":
version: 2.1.1
resolution: "bser@npm:2.1.1"
@@ -7015,6 +7188,23 @@ __metadata:
languageName: node
linkType: hard
+"gql.tada@npm:^1.7.0":
+ version: 1.8.12
+ resolution: "gql.tada@npm:1.8.12"
+ dependencies:
+ "@0no-co/graphql.web": "npm:^1.0.5"
+ "@0no-co/graphqlsp": "npm:^1.12.13"
+ "@gql.tada/cli-utils": "npm:1.7.0"
+ "@gql.tada/internal": "npm:1.0.8"
+ peerDependencies:
+ typescript: ^5.0.0
+ bin:
+ gql-tada: bin/cli.js
+ gql.tada: bin/cli.js
+ checksum: 10c0/011c50a3e02e4b836ce69b01d5a523c1cf9526a031cd8f0d5e14a7505814381922f7ed3f21ae1b4508051fe1f868f1bd836bbea96fcec30c48cc383351a31d8e
+ languageName: node
+ linkType: hard
+
"graceful-fs@npm:^4.1.2, graceful-fs@npm:^4.1.5, graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.11, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9":
version: 4.2.11
resolution: "graceful-fs@npm:4.2.11"
@@ -7029,6 +7219,13 @@ __metadata:
languageName: node
linkType: hard
+"graphql@npm:^15.5.0 || ^16.0.0 || ^17.0.0, graphql@npm:^16.8.1":
+ version: 16.11.0
+ resolution: "graphql@npm:16.11.0"
+ checksum: 10c0/124da7860a2292e9acf2fed0c71fc0f6a9b9ca865d390d112bdd563c1f474357141501c12891f4164fe984315764736ad67f705219c62f7580681d431a85db88
+ languageName: node
+ linkType: hard
+
"has-bigints@npm:^1.0.2":
version: 1.1.0
resolution: "has-bigints@npm:1.1.0"
@@ -9631,6 +9828,27 @@ __metadata:
languageName: node
linkType: hard
+"ox@npm:0.8.6":
+ version: 0.8.6
+ resolution: "ox@npm:0.8.6"
+ dependencies:
+ "@adraffy/ens-normalize": "npm:^1.11.0"
+ "@noble/ciphers": "npm:^1.3.0"
+ "@noble/curves": "npm:^1.9.1"
+ "@noble/hashes": "npm:^1.8.0"
+ "@scure/bip32": "npm:^1.7.0"
+ "@scure/bip39": "npm:^1.6.0"
+ abitype: "npm:^1.0.8"
+ eventemitter3: "npm:5.0.1"
+ peerDependencies:
+ typescript: ">=5.4.0"
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ checksum: 10c0/025c638966c6e569bb38a78a6f9f84bbeb9f5b0a594ef011ab3f81414edcaf5b20d9ea7d8f90471ddafdcb3f21c61f7a2255d35d2032e8daafbc8b20d98d27cf
+ languageName: node
+ linkType: hard
+
"p-filter@npm:^2.1.0":
version: 2.1.0
resolution: "p-filter@npm:2.1.0"
@@ -10527,7 +10745,7 @@ __metadata:
languageName: node
linkType: hard
-"safe-buffer@npm:^5.0.1":
+"safe-buffer@npm:^5.0.1, safe-buffer@npm:^5.1.1":
version: 5.2.1
resolution: "safe-buffer@npm:5.2.1"
checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3
@@ -11017,6 +11235,13 @@ __metadata:
languageName: node
linkType: hard
+"superstruct@npm:^1.0.3":
+ version: 1.0.4
+ resolution: "superstruct@npm:1.0.4"
+ checksum: 10c0/d355f1a96fa314e9df217aa371e8f22854644e7b600b7b0faa36860a8e50f61a60a6f1189ecf166171bf438aa6581bbd0d3adae1a65f03a3c43c62fd843e925c
+ languageName: node
+ linkType: hard
+
"superstruct@npm:^2.0.2":
version: 2.0.2
resolution: "superstruct@npm:2.0.2"
@@ -11553,6 +11778,13 @@ __metadata:
languageName: node
linkType: hard
+"typeforce@npm:^1.11.3":
+ version: 1.18.0
+ resolution: "typeforce@npm:1.18.0"
+ checksum: 10c0/011f57effd9ae6d3dd8bb249e09b4ecadb2c2a3f803b27f977ac8b7782834855930bff971ba549bcd5a8cedc8136d8a977c0b7e050cc67deded948181b7ba3e8
+ languageName: node
+ linkType: hard
+
"typescript@npm:^5.0.2, typescript@npm:^5.0.4, typescript@npm:^5.2.0, typescript@npm:^5.8.3, typescript@npm:~5.8.3":
version: 5.8.3
resolution: "typescript@npm:5.8.3"
@@ -11847,6 +12079,36 @@ __metadata:
languageName: node
linkType: hard
+"varuint-bitcoin@npm:^1.1.2":
+ version: 1.1.2
+ resolution: "varuint-bitcoin@npm:1.1.2"
+ dependencies:
+ safe-buffer: "npm:^5.1.1"
+ checksum: 10c0/3d38f8de8192b7a4fc00abea01ed189f1e1e6aee1ebc4192040c5717d2483e0a6a73873fcf6b3c1910d947d338b671470505705fe40c765dc832255dfa2d4210
+ languageName: node
+ linkType: hard
+
+"viem@npm:^2.21.1":
+ version: 2.33.2
+ resolution: "viem@npm:2.33.2"
+ dependencies:
+ "@noble/curves": "npm:1.9.2"
+ "@noble/hashes": "npm:1.8.0"
+ "@scure/bip32": "npm:1.7.0"
+ "@scure/bip39": "npm:1.6.0"
+ abitype: "npm:1.0.8"
+ isows: "npm:1.0.7"
+ ox: "npm:0.8.6"
+ ws: "npm:8.18.2"
+ peerDependencies:
+ typescript: ">=5.0.4"
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+ checksum: 10c0/4b0cdbb322617897f71f6ffa9efc90f8cfad202f9a90d2275181db79e806a962f5d458e3d8b5f861a81e628c05b9a4ebf7853ebce26283291aec3f54a03a4df3
+ languageName: node
+ linkType: hard
+
"viem@npm:^2.33.1":
version: 2.33.1
resolution: "viem@npm:2.33.1"