@phantom/server-sdk 0.0.2 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,208 +1,70 @@
1
- # Server SDK
1
+ # Phantom Server SDK
2
2
 
3
- This package provides integration with @phantom/openapi-wallet-service for secure wallet management and transaction signing.
3
+ The Phantom Server SDK provides a secure and straightforward way to create and manage wallets, sign transactions, and interact with multiple blockchains from your backend services.
4
4
 
5
- ## Installation
6
-
7
- ```bash
8
- npm install @phantom/server-sdk
9
- ```
10
-
11
- ## Configuration
5
+ ## 📖 Documentation
12
6
 
13
- The SDK requires the following configuration:
7
+ Visit **[docs.phantom.com/server-sdk](https://docs.phantom.com/server-sdk)** for comprehensive documentation including:
14
8
 
15
- - `apiPrivateKey`: Your signing key for authentication (base58 encoded)
16
- - `organizationId`: Your organization ID from Phantom
17
- - `apiBaseUrl`: The wallet API endpoint URL
9
+ - Getting Started Guide
10
+ - Creating and Managing Wallets
11
+ - Signing Transactions
12
+ - Signing Messages
13
+ - Complete API Reference
14
+ - Integration Examples
15
+ - Best Practices
16
+ - Security Considerations
18
17
 
19
- ```typescript
20
- import { ServerSDK } from '@phantom/server-sdk';
18
+ ## Installation
21
19
 
22
- const sdk = new ServerSDK({
23
- apiPrivateKey: 'your-signing-key-base58',
24
- organizationId: 'your-org-id',
25
- apiBaseUrl: 'https://api.phantom.app/v1'
26
- });
20
+ ```bash
21
+ npm install @phantom/server-sdk
27
22
  ```
28
23
 
29
- ## Network Identifiers
30
-
31
- The SDK provides user-friendly enums for CAIP-2 network identifiers:
32
-
33
- ```typescript
34
- import { NetworkId } from '@phantom/server-sdk';
35
-
36
- // Use the NetworkId enum for easy access to CAIP-2 identifiers
37
- const solanaMainnet = NetworkId.SOLANA_MAINNET; // 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'
38
- const ethMainnet = NetworkId.ETHEREUM_MAINNET; // 'eip155:1'
39
- const polygonMainnet = NetworkId.POLYGON_MAINNET; // 'eip155:137'
40
-
41
- // Example usage with SDK methods
42
- const result = await sdk.signAndSendTransaction(
43
- walletId,
44
- transaction,
45
- NetworkId.SOLANA_MAINNET // Instead of hardcoding 'solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp'
46
- );
47
-
48
- // Sign a message on Ethereum
49
- const signature = await sdk.signMessage(
50
- walletId,
51
- 'Hello World',
52
- NetworkId.ETHEREUM_MAINNET
53
- );
54
-
55
-
24
+ ```bash
25
+ yarn add @phantom/server-sdk
56
26
  ```
57
27
 
58
- ### Available Networks
59
-
60
- | Network | Enum Value | CAIP-2 ID |
61
- |---------|-----------|-----------|
62
- | **Solana** | | |
63
- | Mainnet | `NetworkId.SOLANA_MAINNET` | `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp` |
64
- | Devnet | `NetworkId.SOLANA_DEVNET` | `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1` |
65
- | Testnet | `NetworkId.SOLANA_TESTNET` | `solana:4uhcVJyU9pJkvQyS88uRDiswHXSCkY3z` |
66
- | **Ethereum** | | |
67
- | Mainnet | `NetworkId.ETHEREUM_MAINNET` | `eip155:1` |
68
- | Goerli | `NetworkId.ETHEREUM_GOERLI` | `eip155:5` |
69
- | Sepolia | `NetworkId.ETHEREUM_SEPOLIA` | `eip155:11155111` |
70
- | **Polygon** | | |
71
- | Mainnet | `NetworkId.POLYGON_MAINNET` | `eip155:137` |
72
- | Mumbai | `NetworkId.POLYGON_MUMBAI` | `eip155:80001` |
73
- | **Arbitrum** | | |
74
- | One | `NetworkId.ARBITRUM_ONE` | `eip155:42161` |
75
- | Goerli | `NetworkId.ARBITRUM_GOERLI` | `eip155:421613` |
76
- | **Base** | | |
77
- | Mainnet | `NetworkId.BASE_MAINNET` | `eip155:8453` |
78
- | Sepolia | `NetworkId.BASE_SEPOLIA` | `eip155:84532` |
79
-
80
- ## CAIP-2 Network Identifiers
81
-
82
- This SDK uses the CAIP-2 (Chain Agnostic Improvement Proposal 2) standard for network identifiers. CAIP-2 provides a standardized way to identify blockchain networks across different ecosystems.
83
-
84
- ### Format
85
- CAIP-2 identifiers follow the format: `namespace:reference`
86
-
87
- ### Common Network IDs
88
- - **Solana Mainnet**: `solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp`
89
- - **Solana Devnet**: `solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1`
90
- - **Ethereum Mainnet**: `eip155:1`
91
- - **Polygon Mainnet**: `eip155:137`
92
- - **Arbitrum One**: `eip155:42161`
93
- - **Base Mainnet**: `eip155:8453`
94
-
95
- ## Methods
96
-
97
- ### createWallet(walletName?: string)
98
- Creates a new wallet with an optional name. If no name is provided, a default name with timestamp is used.
99
- After creation, it retrieves the public key by signing an empty payload.
100
-
101
- ```typescript
102
- const wallet = await sdk.createWallet('My Main Wallet');
103
- // Returns: {
104
- // walletId: 'wallet-uuid',
105
- // addresses: [{ addressType: 'Solana', address: 'public-key' }]
106
- // }
28
+ ```bash
29
+ pnpm add @phantom/server-sdk
107
30
  ```
108
31
 
109
- ### signAndSendTransaction(walletId: string, transaction: Uint8Array, networkId: string)
110
- Signs a transaction using the wallet service. The transaction should be provided as a Uint8Array and will be encoded as base64 before sending to the KMS.
111
-
112
- The SDK automatically derives the submission configuration from the CAIP-2 network ID. If the network supports transaction submission, Phantom will submit the transaction to the blockchain after signing.
113
-
114
- **Note:** This method returns only the signed transaction data. To get the transaction hash/signature, you need to extract it from the signed transaction.
32
+ ## Quick Start
115
33
 
116
34
  ```typescript
117
- import { NetworkId } from '@phantom/server-sdk';
35
+ import { ServerSDK, NetworkId } from '@phantom/server-sdk';
118
36
 
119
- const transactionBuffer = new Uint8Array([...]); // Your serialized transaction
120
- const result = await sdk.signAndSendTransaction(
121
- 'wallet-id',
122
- transactionBuffer,
123
- NetworkId.SOLANA_MAINNET // Using enum - submission config automatically derived
124
- );
125
-
126
- // Returns: {
127
- // rawTransaction: 'base64-signed-transaction'
128
- // }
129
-
130
- // Extract the transaction signature (hash)
131
- // Note: requires 'import bs58 from "bs58"'
132
- const signedTx = Transaction.from(Buffer.from(result.rawTransaction, 'base64'));
133
- const signature = signedTx.signature
134
- ? bs58.encode(signedTx.signature)
135
- : bs58.encode(signedTx.signatures[0].signature);
136
- ```
37
+ // Initialize the SDK
38
+ const sdk = new ServerSDK({
39
+ organizationId: process.env.PHANTOM_ORGANIZATION_ID!,
40
+ apiPrivateKey: process.env.PHANTOM_PRIVATE_KEY!,
41
+ apiBaseUrl: process.env.PHANTOM_API_URL!
42
+ });
137
43
 
138
- ### signMessage(walletId: string, message: string, networkId: string)
139
- Signs a message with the specified wallet using the signRawPayload method.
44
+ // Create a wallet
45
+ const wallet = await sdk.createWallet('My First Wallet');
46
+ console.log('Wallet ID:', wallet.walletId);
47
+ console.log('Addresses:', wallet.addresses);
140
48
 
141
- ```typescript
49
+ // Sign a message
142
50
  const signature = await sdk.signMessage(
143
- 'wallet-id',
144
- 'Hello World',
145
- NetworkId.SOLANA_MAINNET // Using enum for CAIP-2 network ID
51
+ wallet.walletId,
52
+ 'Hello, Phantom!',
53
+ NetworkId.SOLANA_MAINNET
146
54
  );
147
- // Returns: base64 encoded signature
148
- ```
149
-
150
- ## CAIP-2 Utility Functions
151
-
152
- The SDK exports several utility functions for working with CAIP-2 network identifiers:
153
-
154
- ```typescript
155
- import {
156
- deriveSubmissionConfig,
157
- supportsTransactionSubmission,
158
- getNetworkDescription,
159
- getSupportedNetworkIds,
160
- getNetworkIdsByChain
161
- } from '@phantom/server-sdk';
162
-
163
- // Check if a network supports transaction submission
164
- if (supportsTransactionSubmission('solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp')) {
165
- // Network supports automatic transaction submission
166
- }
167
-
168
- // Get human-readable network description
169
- const description = getNetworkDescription('eip155:137'); // "Polygon Mainnet"
170
-
171
- // List all supported networks
172
- const allNetworks = getSupportedNetworkIds();
173
-
174
- // Get networks for a specific chain
175
- const solanaNetworks = getNetworkIdsByChain('solana');
176
- // ['solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', ...]
55
+ console.log('Signature:', signature);
177
56
  ```
178
57
 
179
- ## Implementation Details
180
-
181
- This SDK uses the @phantom/openapi-wallet-service package which provides:
182
- - `createWallet` - Creates a new wallet and retrieves its public key via signRawPayload
183
- - `signTransaction` - Signs transactions with the wallet's private key
184
- - `signRawPayload` - Signs raw payloads/messages and returns signature with public key
185
-
186
- The SDK handles:
187
- - Network-specific algorithms and curves automatically
188
- - Standard derivation paths for each blockchain
189
- - Base64 encoding for transaction data
190
- - Authentication via Ed25519 signatures
191
- - CAIP-2 network ID parsing and submission config derivation
192
-
193
- ## Authentication
58
+ For complete documentation and examples, visit **[docs.phantom.com/server-sdk](https://docs.phantom.com/server-sdk)**.
194
59
 
195
- The SDK authenticates requests using Ed25519 signatures:
196
- - Each request is signed with your organization's private key
197
- - The signature, public key, and timestamp are added as headers
198
- - This ensures secure communication with the Phantom wallet service
60
+ ## Resources
199
61
 
62
+ - [Documentation](https://docs.phantom.com/server-sdk)
63
+ - [Example Code](https://github.com/phantom/wallet-sdk/tree/main/examples/server-sdk-examples)
64
+ - [Integration Guide](https://docs.phantom.com/server-sdk/integration-guide)
65
+ - [API Reference](https://docs.phantom.com/server-sdk/api-reference)
66
+ - [Changelog](./CHANGELOG.md)
200
67
 
201
- ## Notes
68
+ ## License
202
69
 
203
- - The wallet ID is a UUID assigned by the service when creating the wallet
204
- - Public keys are retrieved using the signRawPayload method with an empty payload
205
- - Transaction hashes are not returned by the signing service - they're generated after blockchain submission
206
- - The service returns the public key that signed the transaction in the signature field
207
- - Default wallet names include a timestamp to ensure uniqueness
208
- - Message signing supports both Solana (Ed25519) and Ethereum (Secp256k1) networks
70
+ This SDK is distributed under the MIT License. See the [LICENSE](../../LICENSE) file for details.
package/dist/auth.js CHANGED
@@ -16,7 +16,7 @@ function createAuthenticatedAxiosInstance(signingKeypair) {
16
16
  const requestBody = typeof config.data === "string" ? config.data : JSON.stringify(config.data);
17
17
  const dataUtf8 = Buffer.from(requestBody, "utf8");
18
18
  const signature = tweetnacl_1.default.sign.detached(dataUtf8, signingKeypair.secretKey);
19
- config.headers["X-Phantom-Sig"] = Buffer.from(signature).toString("base64");
19
+ config.headers["X-Phantom-Sig"] = Buffer.from(signature).toString("base64url");
20
20
  return config;
21
21
  });
22
22
  return instance;
@@ -1,10 +1,11 @@
1
1
  import { DerivationInfoCurveEnum, DerivationInfoAddressFormatEnum, Algorithm } from '@phantom/openapi-wallet-service';
2
+ import { NetworkId } from './caip2-mappings';
2
3
  /**
3
4
  * Default derivation paths for different blockchain networks
4
5
  */
5
6
  export declare enum DerivationPath {
6
7
  Solana = "m/44'/501'/0'/0'",
7
- Ethereum = "m/44'/60'/0'/0",
8
+ Ethereum = "m/44'/60'/0'/0/0",
8
9
  Bitcoin = "m/84'/0'/0'/0",
9
10
  Sui = "m/44'/784'/0'/0'/0'"
10
11
  }
@@ -24,4 +25,4 @@ export interface NetworkConfig {
24
25
  /**
25
26
  * Get complete network configuration
26
27
  */
27
- export declare function getNetworkConfig(networkId: string): NetworkConfig;
28
+ export declare function getNetworkConfig(networkId: NetworkId): NetworkConfig | null;
package/dist/constants.js CHANGED
@@ -12,7 +12,7 @@ var DerivationPath;
12
12
  // Solana - BIP44 standard for Solana (coin type 501)
13
13
  DerivationPath["Solana"] = "m/44'/501'/0'/0'";
14
14
  // Ethereum - BIP44 standard for Ethereum and all EVM-compatible chains (coin type 60)
15
- DerivationPath["Ethereum"] = "m/44'/60'/0'/0";
15
+ DerivationPath["Ethereum"] = "m/44'/60'/0'/0/0";
16
16
  // Bitcoin - BIP44 standard for Bitcoin (coin type 0)
17
17
  DerivationPath["Bitcoin"] = "m/84'/0'/0'/0";
18
18
  // Sui - BIP44 standard for Sui (coin type 784)
@@ -68,7 +68,7 @@ function getNetworkConfig(networkId) {
68
68
  algorithm: openapi_wallet_service_1.Algorithm.secp256k1,
69
69
  addressFormat: openapi_wallet_service_1.DerivationInfoAddressFormatEnum.bitcoinSegwit // Bitcoin uses a different format, but for SDK consistency we use Ethereum format
70
70
  };
71
- default:
71
+ case 'eip155': // EVM chains use eip155 prefix
72
72
  // All EVM-compatible chains (Ethereum, Polygon, BSC, Arbitrum, etc.)
73
73
  return {
74
74
  derivationPath: DerivationPath.Ethereum,
@@ -76,5 +76,7 @@ function getNetworkConfig(networkId) {
76
76
  algorithm: openapi_wallet_service_1.Algorithm.secp256k1,
77
77
  addressFormat: openapi_wallet_service_1.DerivationInfoAddressFormatEnum.ethereum // EVM chains use Ethereum address format
78
78
  };
79
+ default:
80
+ return null;
79
81
  }
80
82
  }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { ServerSDKConfig, CreateWalletResult, Transaction, SignedTransaction } from "./types";
1
+ import { ServerSDKConfig, CreateWalletResult, Transaction, SignedTransaction, GetWalletsResult } from "./types";
2
+ import { NetworkId } from "./caip2-mappings";
2
3
  export interface SubmissionConfig {
3
4
  chain: string;
4
5
  network: string;
@@ -10,11 +11,12 @@ export declare class ServerSDK {
10
11
  private signingKeypair;
11
12
  constructor(config: ServerSDKConfig);
12
13
  createWallet(walletName?: string): Promise<CreateWalletResult>;
13
- signAndSendTransaction(walletId: string, transaction: Transaction, networkId: string): Promise<SignedTransaction>;
14
+ signAndSendTransaction(walletId: string, transaction: Transaction, networkId: NetworkId): Promise<SignedTransaction>;
14
15
  getWalletAddresses(walletId: string, derivationPaths?: string[]): Promise<{
15
16
  addressType: string;
16
17
  address: string;
17
18
  }[]>;
18
- signMessage(walletId: string, message: string, networkId: string): Promise<string>;
19
+ signMessage(walletId: string, message: string, networkId: NetworkId): Promise<string>;
20
+ getWallets(limit?: number, offset?: number): Promise<GetWalletsResult>;
19
21
  }
20
22
  export * from "./types";
package/dist/index.js CHANGED
@@ -97,47 +97,43 @@ class ServerSDK {
97
97
  async signAndSendTransaction(walletId, transaction, networkId) {
98
98
  try {
99
99
  // Encode the Uint8Array as a base64 string
100
- const encodedTransaction = Buffer.from(transaction).toString('base64');
100
+ const encodedTransaction = Buffer.from(transaction).toString('base64url');
101
101
  const submissionConfig = (0, caip2_mappings_1.deriveSubmissionConfig)(networkId);
102
102
  // If we don't have a submission config, the transaction will only be signed, not submitted
103
103
  if (!submissionConfig) {
104
104
  console.warn(`No submission config available for network ${networkId}. Transaction will be signed but not submitted.`);
105
105
  }
106
- // For Solana transactions
107
- if (networkId.startsWith("solana:")) {
108
- // Get network configuration
109
- const networkConfig = (0, constants_1.getNetworkConfig)(networkId);
110
- const derivationInfo = {
111
- derivationPath: networkConfig.derivationPath,
112
- curve: networkConfig.curve,
113
- addressFormat: networkConfig.addressFormat,
114
- };
115
- // Sign transaction request - only include submissionConfig if available
116
- const signRequest = {
117
- organizationId: this.config.organizationId,
118
- walletId: walletId,
119
- transaction: encodedTransaction,
120
- derivationInfo: derivationInfo,
121
- };
122
- // Add submission config if available
123
- if (submissionConfig) {
124
- signRequest.submissionConfig = submissionConfig;
125
- }
126
- const request = {
127
- method: openapi_wallet_service_1.SignTransactionMethodEnum.signTransaction,
128
- params: signRequest,
129
- timestampMs: Date.now(),
130
- };
131
- const response = await this.kmsApi.postKmsRpc(request);
132
- const result = response.data.result;
133
- return {
134
- rawTransaction: result.transaction, // Base64 encoded signed transaction
135
- };
106
+ // Get network configuration
107
+ const networkConfig = (0, constants_1.getNetworkConfig)(networkId);
108
+ if (!networkConfig) {
109
+ throw new Error(`Unsupported network ID: ${networkId}`);
136
110
  }
137
- else {
138
- // For EVM chains (future implementation)
139
- throw new Error("EVM transaction signing not yet implemented");
111
+ const derivationInfo = {
112
+ derivationPath: networkConfig.derivationPath,
113
+ curve: networkConfig.curve,
114
+ addressFormat: networkConfig.addressFormat,
115
+ };
116
+ // Sign transaction request - only include submissionConfig if available
117
+ const signRequest = {
118
+ organizationId: this.config.organizationId,
119
+ walletId: walletId,
120
+ transaction: encodedTransaction,
121
+ derivationInfo: derivationInfo,
122
+ };
123
+ // Add submission config if available
124
+ if (submissionConfig) {
125
+ signRequest.submissionConfig = submissionConfig;
140
126
  }
127
+ const request = {
128
+ method: openapi_wallet_service_1.SignTransactionMethodEnum.signTransaction,
129
+ params: signRequest,
130
+ timestampMs: Date.now(),
131
+ };
132
+ const response = await this.kmsApi.postKmsRpc(request);
133
+ const result = response.data.result;
134
+ return {
135
+ rawTransaction: result.transaction, // Base64 encoded signed transaction
136
+ };
141
137
  }
142
138
  catch (error) {
143
139
  console.error("Failed to sign and send transaction:", error.response?.data || error.message);
@@ -175,19 +171,21 @@ class ServerSDK {
175
171
  }
176
172
  async signMessage(walletId, message, networkId) {
177
173
  try {
178
- // Convert message to byte array
179
- const messageBytes = Array.from(Buffer.from(message, "utf8"));
180
174
  // Get network configuration
181
175
  const networkConfig = (0, constants_1.getNetworkConfig)(networkId);
176
+ if (!networkConfig) {
177
+ throw new Error(`Unsupported network ID: ${networkId}`);
178
+ }
182
179
  const derivationInfo = {
183
180
  derivationPath: networkConfig.derivationPath,
184
181
  curve: networkConfig.curve,
185
182
  addressFormat: networkConfig.addressFormat,
186
183
  };
184
+ const base64StringMessage = Buffer.from(message, "utf8").toString("base64url");
187
185
  const signRequest = {
188
186
  organizationId: this.config.organizationId,
189
187
  walletId: walletId,
190
- payload: messageBytes,
188
+ payload: base64StringMessage,
191
189
  algorithm: networkConfig.algorithm,
192
190
  derivationInfo: derivationInfo,
193
191
  };
@@ -206,6 +204,36 @@ class ServerSDK {
206
204
  throw new Error(`Failed to sign message: ${error.response?.data?.message || error.message}`);
207
205
  }
208
206
  }
207
+ async getWallets(limit, offset) {
208
+ try {
209
+ const request = {
210
+ method: "getOrganizationWallets",
211
+ params: {
212
+ organizationId: this.config.organizationId,
213
+ limit: limit || 20,
214
+ offset: offset || 0,
215
+ },
216
+ timestampMs: Date.now(),
217
+ };
218
+ console.log("Fetching wallets for organization:", this.config.organizationId);
219
+ const response = await this.kmsApi.postKmsRpc(request);
220
+ const result = response.data.result;
221
+ console.log(`Fetched ${result.wallets.length} wallets out of ${result.totalCount} total`);
222
+ return {
223
+ wallets: result.wallets.map((wallet) => ({
224
+ walletId: wallet.walletId,
225
+ walletName: wallet.walletName,
226
+ })),
227
+ totalCount: result.totalCount,
228
+ limit: result.limit,
229
+ offset: result.offset,
230
+ };
231
+ }
232
+ catch (error) {
233
+ console.error("Failed to get wallets:", error.response?.data || error.message);
234
+ throw new Error(`Failed to get wallets: ${error.response?.data?.message || error.message}`);
235
+ }
236
+ }
209
237
  }
210
238
  exports.ServerSDK = ServerSDK;
211
239
  __exportStar(require("./types"), exports);
package/dist/types.d.ts CHANGED
@@ -17,3 +17,13 @@ export type Transaction = Uint8Array;
17
17
  export interface SignedTransaction {
18
18
  rawTransaction: string;
19
19
  }
20
+ export interface Wallet {
21
+ walletId: string;
22
+ walletName: string;
23
+ }
24
+ export interface GetWalletsResult {
25
+ wallets: Wallet[];
26
+ totalCount: number;
27
+ limit: number;
28
+ offset: number;
29
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/server-sdk",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "description": "Server SDK for Phantom Wallet",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",