@phantom/server-sdk 0.0.2 → 0.0.3
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 +65 -45
- package/dist/constants.d.ts +3 -2
- package/dist/constants.js +4 -2
- package/dist/index.d.ts +5 -3
- package/dist/index.js +64 -36
- package/dist/types.d.ts +10 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# Server SDK
|
|
1
|
+
# Phantom Server SDK
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The Phantom Server SDK enables secure wallet creation, message signing and transaction signing and submission for your applications.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -10,19 +10,15 @@ npm install @phantom/server-sdk
|
|
|
10
10
|
|
|
11
11
|
## Configuration
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
- `apiPrivateKey`: Your signing key for authentication (base58 encoded)
|
|
16
|
-
- `organizationId`: Your organization ID from Phantom
|
|
17
|
-
- `apiBaseUrl`: The wallet API endpoint URL
|
|
13
|
+
To get started, initialize the SDK with your credentials:
|
|
18
14
|
|
|
19
15
|
```typescript
|
|
20
16
|
import { ServerSDK } from '@phantom/server-sdk';
|
|
21
17
|
|
|
22
18
|
const sdk = new ServerSDK({
|
|
23
|
-
apiPrivateKey: 'your-
|
|
24
|
-
organizationId: 'your-org-id',
|
|
25
|
-
apiBaseUrl: 'https://api.phantom.app/
|
|
19
|
+
apiPrivateKey: 'your-private-key', // Base58 encoded private key
|
|
20
|
+
organizationId: 'your-org-id', // Your organization ID
|
|
21
|
+
apiBaseUrl: 'https://api.phantom.app/wallet'
|
|
26
22
|
});
|
|
27
23
|
```
|
|
28
24
|
|
|
@@ -95,23 +91,24 @@ CAIP-2 identifiers follow the format: `namespace:reference`
|
|
|
95
91
|
## Methods
|
|
96
92
|
|
|
97
93
|
### createWallet(walletName?: string)
|
|
98
|
-
Creates a new wallet
|
|
99
|
-
After creation, it retrieves the public key by signing an empty payload.
|
|
94
|
+
Creates a new wallet in your organization. Each wallet supports multiple chains.
|
|
100
95
|
|
|
101
96
|
```typescript
|
|
102
97
|
const wallet = await sdk.createWallet('My Main Wallet');
|
|
103
98
|
// Returns: {
|
|
104
99
|
// walletId: 'wallet-uuid',
|
|
105
|
-
// addresses: [
|
|
100
|
+
// addresses: [
|
|
101
|
+
// { addressType: 'Solana', address: '...' },
|
|
102
|
+
// { addressType: 'Ethereum', address: '...' },
|
|
103
|
+
// { addressType: 'BitcoinSegwit', address: '...' },
|
|
104
|
+
// { addressType: 'Sui', address: '...' }
|
|
105
|
+
// ]
|
|
106
106
|
// }
|
|
107
107
|
```
|
|
108
108
|
|
|
109
109
|
### signAndSendTransaction(walletId: string, transaction: Uint8Array, networkId: string)
|
|
110
|
-
Signs a transaction
|
|
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.
|
|
110
|
+
Signs a transaction and tries to submits it to the blockchain. The SDK automatically handles network-specific requirements.
|
|
111
|
+
If the networkId is not supported for sending, the transaction will only be signed.
|
|
115
112
|
|
|
116
113
|
```typescript
|
|
117
114
|
import { NetworkId } from '@phantom/server-sdk';
|
|
@@ -120,11 +117,12 @@ const transactionBuffer = new Uint8Array([...]); // Your serialized transaction
|
|
|
120
117
|
const result = await sdk.signAndSendTransaction(
|
|
121
118
|
'wallet-id',
|
|
122
119
|
transactionBuffer,
|
|
123
|
-
NetworkId.SOLANA_MAINNET
|
|
120
|
+
NetworkId.SOLANA_MAINNET
|
|
124
121
|
);
|
|
125
122
|
|
|
126
123
|
// Returns: {
|
|
127
124
|
// rawTransaction: 'base64-signed-transaction'
|
|
125
|
+
// txHash: 'tx-hash-string'
|
|
128
126
|
// }
|
|
129
127
|
|
|
130
128
|
// Extract the transaction signature (hash)
|
|
@@ -136,17 +134,47 @@ const signature = signedTx.signature
|
|
|
136
134
|
```
|
|
137
135
|
|
|
138
136
|
### signMessage(walletId: string, message: string, networkId: string)
|
|
139
|
-
Signs a message with the specified wallet
|
|
137
|
+
Signs a message with the specified wallet.
|
|
140
138
|
|
|
141
139
|
```typescript
|
|
142
140
|
const signature = await sdk.signMessage(
|
|
143
141
|
'wallet-id',
|
|
144
142
|
'Hello World',
|
|
145
|
-
NetworkId.SOLANA_MAINNET
|
|
143
|
+
NetworkId.SOLANA_MAINNET
|
|
146
144
|
);
|
|
147
145
|
// Returns: base64 encoded signature
|
|
148
146
|
```
|
|
149
147
|
|
|
148
|
+
### getWallets(limit?: number, offset?: number)
|
|
149
|
+
Retrieves all wallets for your organization with pagination support.
|
|
150
|
+
|
|
151
|
+
```typescript
|
|
152
|
+
// Get first 10 wallets
|
|
153
|
+
const result = await sdk.getWallets(10, 0);
|
|
154
|
+
// Returns: {
|
|
155
|
+
// wallets: [{ walletId: '...', walletName: '...' }, ...],
|
|
156
|
+
// totalCount: 25,
|
|
157
|
+
// limit: 10,
|
|
158
|
+
// offset: 0
|
|
159
|
+
// }
|
|
160
|
+
|
|
161
|
+
// Get all wallets (default limit: 20)
|
|
162
|
+
const allWallets = await sdk.getWallets();
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### getWalletAddresses(walletId: string, derivationPaths?: string[])
|
|
166
|
+
Retrieves addresses for a specific wallet across different blockchains.
|
|
167
|
+
|
|
168
|
+
```typescript
|
|
169
|
+
const addresses = await sdk.getWalletAddresses('wallet-id');
|
|
170
|
+
// Returns: [
|
|
171
|
+
// { addressType: 'Solana', address: '...' },
|
|
172
|
+
// { addressType: 'Ethereum', address: '...' },
|
|
173
|
+
// { addressType: 'Bitcoin', address: '...' },
|
|
174
|
+
// { addressType: 'Sui', address: '...' }
|
|
175
|
+
// ]
|
|
176
|
+
```
|
|
177
|
+
|
|
150
178
|
## CAIP-2 Utility Functions
|
|
151
179
|
|
|
152
180
|
The SDK exports several utility functions for working with CAIP-2 network identifiers:
|
|
@@ -176,33 +204,25 @@ const solanaNetworks = getNetworkIdsByChain('solana');
|
|
|
176
204
|
// ['solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp', 'solana:EtWTRABZaYq6iMfeYKouRu166VU2xqa1', ...]
|
|
177
205
|
```
|
|
178
206
|
|
|
179
|
-
##
|
|
207
|
+
## Security Best Practices
|
|
180
208
|
|
|
181
|
-
|
|
182
|
-
-
|
|
183
|
-
-
|
|
184
|
-
-
|
|
209
|
+
- **Never expose your private key** in client-side code or commit it to version control
|
|
210
|
+
- Store your credentials securely using environment variables or secret management systems
|
|
211
|
+
- Each wallet is isolated and can only be accessed by your organization
|
|
212
|
+
- All API requests are authenticated using cryptographic signatures
|
|
185
213
|
|
|
186
|
-
|
|
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
|
|
214
|
+
## Error Handling
|
|
192
215
|
|
|
193
|
-
|
|
194
|
-
|
|
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
|
|
216
|
+
All SDK methods throw descriptive errors when operations fail:
|
|
199
217
|
|
|
218
|
+
```typescript
|
|
219
|
+
try {
|
|
220
|
+
const wallet = await sdk.createWallet();
|
|
221
|
+
} catch (error) {
|
|
222
|
+
console.error('Failed to create wallet:', error.message);
|
|
223
|
+
}
|
|
224
|
+
```
|
|
200
225
|
|
|
201
|
-
##
|
|
226
|
+
## Support
|
|
202
227
|
|
|
203
|
-
|
|
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
|
|
228
|
+
For detailed integration examples and best practices, see the [Integration Guide](./INTEGRATION.md).
|
package/dist/constants.d.ts
CHANGED
|
@@ -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:
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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
|
@@ -103,41 +103,37 @@ class ServerSDK {
|
|
|
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
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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("base64");
|
|
187
185
|
const signRequest = {
|
|
188
186
|
organizationId: this.config.organizationId,
|
|
189
187
|
walletId: walletId,
|
|
190
|
-
payload:
|
|
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
|
+
}
|