@phantom/parsers 1.0.0-beta.7 → 1.0.0-beta.9

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,6 +1,6 @@
1
1
  # @phantom/parsers
2
2
 
3
- A utility package for parsing and converting various message and transaction formats into base64url format for use with Phantom's API. This package provides a unified interface for handling different blockchain transaction formats and message types across multiple networks.
3
+ A utility package for parsing and converting transaction formats into base64url format for use with Phantom's API. This package provides a unified interface for handling different blockchain transaction formats across multiple networks.
4
4
 
5
5
  ## Installation
6
6
 
@@ -12,10 +12,7 @@ yarn add @phantom/parsers
12
12
 
13
13
  ## Overview
14
14
 
15
- The parsers package provides two main functions:
16
-
17
- - **`parseMessage`** - Converts various message formats to base64url
18
- - **`parseTransactionToBase64Url`** - Converts various transaction formats to base64url for different blockchain networks
15
+ - **`parseToKmsTransaction`** - Converts various transaction formats to base64url for different blockchain networks
19
16
 
20
17
  ## Supported Networks
21
18
 
@@ -26,40 +23,9 @@ The parsers package provides two main functions:
26
23
 
27
24
  ## API Reference
28
25
 
29
- ### parseMessage(message)
30
-
31
- Converts various message formats to base64url encoding.
32
-
33
- **Parameters:**
34
-
35
- - `message` (string | Uint8Array | Buffer) - The message to parse
36
-
37
- **Returns:**
38
-
39
- - `ParsedMessage` object with:
40
- - `base64url` (string) - Base64url encoded message
41
- - `originalFormat` (string) - The detected input format
42
-
43
- **Example:**
44
-
45
- ```typescript
46
- import { parseMessage } from "@phantom/parsers";
47
-
48
- // Plain text message
49
- const result1 = parseMessage("Hello, Phantom!");
50
- console.log(result1.base64url); // "SGVsbG8sIFBoYW50b20h"
51
- console.log(result1.originalFormat); // "string"
52
-
53
- // Uint8Array
54
- const bytes = new TextEncoder().encode("Hello, Phantom!");
55
- const result2 = parseMessage(bytes);
56
- console.log(result2.base64url); // "SGVsbG8sIFBoYW50b20h"
57
- console.log(result2.originalFormat); // "bytes"
58
- ```
59
-
60
- ### parseTransactionToBase64Url(transaction, networkId)
26
+ ### parseToKmsTransaction(transaction, networkId)
61
27
 
62
- Converts various transaction formats to base64url encoding based on the target network.
28
+ Converts various transaction formats to different encoding based on the target network.
63
29
 
64
30
  **Parameters:**
65
31
 
@@ -78,25 +44,25 @@ Converts various transaction formats to base64url encoding based on the target n
78
44
 
79
45
  ```typescript
80
46
  import { Transaction } from "@solana/web3.js";
81
- import { parseTransactionToBase64Url } from "@phantom/parsers";
47
+ import { parseToKmsTransaction } from "@phantom/parsers";
82
48
  import { NetworkId } from "@phantom/client";
83
49
 
84
50
  // Solana Web3.js Transaction
85
51
  const transaction = new Transaction().add(/* instructions */);
86
- const result = await parseTransactionToBase64Url(transaction, NetworkId.SOLANA_MAINNET);
52
+ const result = await parseToKmsTransaction(transaction, NetworkId.SOLANA_MAINNET);
87
53
 
88
54
  // Raw bytes
89
55
  const rawBytes = new Uint8Array([1, 2, 3, 4]);
90
- const result2 = await parseTransactionToBase64Url(rawBytes, NetworkId.SOLANA_MAINNET);
56
+ const result2 = await parseToKmsTransaction(rawBytes, NetworkId.SOLANA_MAINNET);
91
57
 
92
58
  // Hex string
93
- const result3 = await parseTransactionToBase64Url("0x01020304", NetworkId.SOLANA_MAINNET);
59
+ const result3 = await parseToKmsTransaction("0x01020304", NetworkId.SOLANA_MAINNET);
94
60
  ```
95
61
 
96
62
  ### Ethereum/EVM
97
63
 
98
64
  ```typescript
99
- import { parseTransactionToBase64Url } from "@phantom/parsers";
65
+ import { parseToKmsTransaction } from "@phantom/parsers";
100
66
  import { NetworkId } from "@phantom/client";
101
67
 
102
68
  // Viem/Ethers transaction object
@@ -108,45 +74,45 @@ const evmTransaction = {
108
74
  gasPrice: 20000000000n, // 20 gwei
109
75
  };
110
76
 
111
- const result = await parseTransactionToBase64Url(evmTransaction, NetworkId.ETHEREUM_MAINNET);
77
+ const result = await parseToKmsTransaction(evmTransaction, NetworkId.ETHEREUM_MAINNET);
112
78
 
113
79
  // Raw transaction bytes
114
80
  const rawTx = new Uint8Array([
115
81
  /* transaction bytes */
116
82
  ]);
117
- const result2 = await parseTransactionToBase64Url(rawTx, NetworkId.ETHEREUM_MAINNET);
83
+ const result2 = await parseToKmsTransaction(rawTx, NetworkId.ETHEREUM_MAINNET);
118
84
 
119
85
  // Hex-encoded transaction
120
- const result3 = await parseTransactionToBase64Url("0xf86c...", NetworkId.ETHEREUM_MAINNET);
86
+ const result3 = await parseToKmsTransaction("0xf86c...", NetworkId.ETHEREUM_MAINNET);
121
87
  ```
122
88
 
123
89
  ### Bitcoin
124
90
 
125
91
  ```typescript
126
- import { parseTransactionToBase64Url } from "@phantom/parsers";
92
+ import { parseToKmsTransaction } from "@phantom/parsers";
127
93
  import { NetworkId } from "@phantom/client";
128
94
 
129
95
  // Raw transaction bytes
130
96
  const bitcoinTx = new Uint8Array([
131
97
  /* bitcoin transaction bytes */
132
98
  ]);
133
- const result = await parseTransactionToBase64Url(bitcoinTx, NetworkId.BITCOIN_MAINNET);
99
+ const result = await parseToKmsTransaction(bitcoinTx, NetworkId.BITCOIN_MAINNET);
134
100
 
135
101
  // Hex-encoded transaction
136
- const result2 = await parseTransactionToBase64Url("0x0100000001...", NetworkId.BITCOIN_MAINNET);
102
+ const result2 = await parseToKmsTransaction("0x0100000001...", NetworkId.BITCOIN_MAINNET);
137
103
  ```
138
104
 
139
105
  ### Sui
140
106
 
141
107
  ```typescript
142
- import { parseTransactionToBase64Url } from "@phantom/parsers";
108
+ import { parseToKmsTransaction } from "@phantom/parsers";
143
109
  import { NetworkId } from "@phantom/client";
144
110
 
145
111
  // Sui transaction bytes
146
112
  const suiTx = new Uint8Array([
147
113
  /* sui transaction bytes */
148
114
  ]);
149
- const result = await parseTransactionToBase64Url(suiTx, NetworkId.SUI_MAINNET);
115
+ const result = await parseToKmsTransaction(suiTx, NetworkId.SUI_MAINNET);
150
116
  ```
151
117
 
152
118
  ## Format Detection
@@ -184,7 +150,7 @@ The parsers will throw descriptive errors for:
184
150
 
185
151
  ```typescript
186
152
  try {
187
- const result = await parseTransactionToBase64Url(invalidData, "unsupported:network");
153
+ const result = await parseToKmsTransaction(invalidData, "unsupported:network");
188
154
  } catch (error) {
189
155
  console.error("Parsing failed:", error.message);
190
156
  // "Unsupported network: unsupported"
package/dist/index.d.ts CHANGED
@@ -23,6 +23,7 @@ interface ParsedTransactionResult {
23
23
  declare function parseSignMessageResponse(base64Response: string, networkId: NetworkId): ParsedSignatureResult;
24
24
  /**
25
25
  * Parse a transaction response from base64 rawTransaction to extract hash
26
+ * For Ethereum chains, converts base64url to hex format
26
27
  */
27
28
  declare function parseTransactionResponse(base64RawTransaction: string, networkId: NetworkId, hash?: string): ParsedTransactionResult;
28
29
  /**
@@ -32,21 +33,19 @@ declare function parseTransactionResponse(base64RawTransaction: string, networkI
32
33
  declare function parseSolanaSignedTransaction(base64RawTransaction: string): Transaction | VersionedTransaction | null;
33
34
 
34
35
  interface ParsedTransaction {
35
- base64url: string;
36
+ /** The parsed transaction string (base64url for Solana/Sui/Bitcoin, RLP-encoded hex for EVM) */
37
+ parsed?: string;
38
+ /** Original format of the input transaction */
36
39
  originalFormat: string;
37
40
  }
38
- interface ParsedMessage {
39
- base64url: string;
40
- }
41
41
 
42
42
  /**
43
- * Parse a message to base64url format for the client
44
- */
45
- declare function parseMessage(message: string): ParsedMessage;
46
- /**
47
- * Parse a transaction to base64url format based on network type
43
+ * Parse a transaction to KMS format based on network type
44
+ * - Solana: base64url encoding
45
+ * - EVM chains: hex encoding
46
+ * - Sui, Bitcoin: base64url encoding
48
47
  */
49
- declare function parseTransactionToBase64Url(transaction: any, networkId: NetworkId): Promise<ParsedTransaction>;
48
+ declare function parseToKmsTransaction(transaction: any, networkId: NetworkId): Promise<ParsedTransaction>;
50
49
  declare function parseSolanaKitTransactionToSolanaWeb3js(transaction: Transaction$1): any;
51
50
 
52
- export { ParsedMessage, ParsedSignatureResult, ParsedTransaction, ParsedTransactionResult, parseMessage, parseSignMessageResponse, parseSolanaKitTransactionToSolanaWeb3js, parseSolanaSignedTransaction, parseTransactionResponse, parseTransactionToBase64Url };
51
+ export { ParsedSignatureResult, ParsedTransaction, ParsedTransactionResult, parseSignMessageResponse, parseSolanaKitTransactionToSolanaWeb3js, parseSolanaSignedTransaction, parseToKmsTransaction, parseTransactionResponse };
package/dist/index.js CHANGED
@@ -30,21 +30,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
- parseMessage: () => parseMessage,
34
33
  parseSignMessageResponse: () => parseSignMessageResponse,
35
34
  parseSolanaKitTransactionToSolanaWeb3js: () => parseSolanaKitTransactionToSolanaWeb3js,
36
35
  parseSolanaSignedTransaction: () => parseSolanaSignedTransaction,
37
- parseTransactionResponse: () => parseTransactionResponse,
38
- parseTransactionToBase64Url: () => parseTransactionToBase64Url
36
+ parseToKmsTransaction: () => parseToKmsTransaction,
37
+ parseTransactionResponse: () => parseTransactionResponse
39
38
  });
40
39
  module.exports = __toCommonJS(src_exports);
41
40
  var import_base64url2 = require("@phantom/base64url");
42
41
  var import_transactions = require("@solana/transactions");
43
42
  var import_buffer2 = require("buffer");
43
+ var import_ethers = require("ethers");
44
44
 
45
45
  // src/response-parsers.ts
46
46
  var import_base64url = require("@phantom/base64url");
47
47
  var import_constants = require("@phantom/constants");
48
+ var import_utils = require("@phantom/utils");
48
49
  var import_web3 = require("@solana/web3.js");
49
50
  var import_bs58 = __toESM(require("bs58"));
50
51
  var import_buffer = require("buffer");
@@ -69,15 +70,24 @@ function parseSignMessageResponse(base64Response, networkId) {
69
70
  }
70
71
  }
71
72
  function parseTransactionResponse(base64RawTransaction, networkId, hash) {
73
+ let rawTransaction = base64RawTransaction;
74
+ if ((0, import_utils.isEthereumChain)(networkId)) {
75
+ try {
76
+ const txBytes = (0, import_base64url.base64urlDecode)(base64RawTransaction);
77
+ rawTransaction = "0x" + import_buffer.Buffer.from(txBytes).toString("hex");
78
+ } catch (error) {
79
+ rawTransaction = base64RawTransaction.startsWith("0x") ? base64RawTransaction : "0x" + base64RawTransaction;
80
+ }
81
+ }
72
82
  if (hash) {
73
83
  return {
74
84
  hash,
75
- rawTransaction: base64RawTransaction,
85
+ rawTransaction,
76
86
  blockExplorer: (0, import_constants.getExplorerUrl)(networkId, "transaction", hash)
77
87
  };
78
88
  } else {
79
89
  return {
80
- rawTransaction: base64RawTransaction
90
+ rawTransaction
81
91
  };
82
92
  }
83
93
  }
@@ -97,27 +107,12 @@ function parseSolanaSignatureResponse(base64Response) {
97
107
  }
98
108
  }
99
109
  function parseEVMSignatureResponse(base64Response) {
100
- try {
101
- const signatureBytes = (0, import_base64url.base64urlDecode)(base64Response);
102
- if (signatureBytes.length === 65) {
103
- const recoveryId = signatureBytes[64];
104
- if (recoveryId === 0 || recoveryId === 1) {
105
- signatureBytes[64] = recoveryId + 27;
106
- }
107
- }
108
- const signature = "0x" + import_buffer.Buffer.from(signatureBytes).toString("hex");
109
- return {
110
- signature,
111
- rawSignature: base64Response
112
- // Note: Most block explorers don't have direct signature lookup, only transaction lookup
113
- };
114
- } catch (error) {
115
- const signature = base64Response.startsWith("0x") ? base64Response : "0x" + base64Response;
116
- return {
117
- signature,
118
- rawSignature: base64Response
119
- };
120
- }
110
+ const signatureBytes = (0, import_base64url.base64urlDecode)(base64Response);
111
+ const signature = "0x" + import_buffer.Buffer.from(signatureBytes).toString("hex");
112
+ return {
113
+ signature,
114
+ rawSignature: base64Response
115
+ };
121
116
  }
122
117
  function parseSuiSignatureResponse(base64Response) {
123
118
  try {
@@ -168,12 +163,7 @@ function parseSolanaSignedTransaction(base64RawTransaction) {
168
163
  }
169
164
 
170
165
  // src/index.ts
171
- function parseMessage(message) {
172
- return {
173
- base64url: (0, import_base64url2.stringToBase64url)(message)
174
- };
175
- }
176
- async function parseTransactionToBase64Url(transaction, networkId) {
166
+ async function parseToKmsTransaction(transaction, networkId) {
177
167
  const networkPrefix = networkId.split(":")[0].toLowerCase();
178
168
  switch (networkPrefix) {
179
169
  case "solana":
@@ -184,7 +174,7 @@ async function parseTransactionToBase64Url(transaction, networkId) {
184
174
  case "optimism":
185
175
  case "arbitrum":
186
176
  case "base":
187
- return parseEVMTransactionToBase64Url(transaction);
177
+ return parseEVMTransactionToHex(transaction);
188
178
  case "sui":
189
179
  return await parseSuiTransactionToBase64Url(transaction);
190
180
  case "bitcoin":
@@ -196,7 +186,7 @@ async function parseTransactionToBase64Url(transaction, networkId) {
196
186
  function parseSolanaTransactionToBase64Url(transaction) {
197
187
  if (transaction?.messageBytes != null) {
198
188
  return {
199
- base64url: (0, import_base64url2.base64urlEncode)(transaction.messageBytes),
189
+ parsed: (0, import_base64url2.base64urlEncode)(transaction.messageBytes),
200
190
  originalFormat: "@solana/kit"
201
191
  };
202
192
  }
@@ -206,13 +196,13 @@ function parseSolanaTransactionToBase64Url(transaction) {
206
196
  verifySignatures: false
207
197
  });
208
198
  return {
209
- base64url: (0, import_base64url2.base64urlEncode)(serialized),
199
+ parsed: (0, import_base64url2.base64urlEncode)(serialized),
210
200
  originalFormat: "@solana/web3.js"
211
201
  };
212
202
  }
213
203
  if (transaction instanceof Uint8Array) {
214
204
  return {
215
- base64url: (0, import_base64url2.base64urlEncode)(transaction),
205
+ parsed: (0, import_base64url2.base64urlEncode)(transaction),
216
206
  originalFormat: "bytes"
217
207
  };
218
208
  }
@@ -220,7 +210,7 @@ function parseSolanaTransactionToBase64Url(transaction) {
220
210
  try {
221
211
  const bytes = import_buffer2.Buffer.from(transaction, "base64");
222
212
  return {
223
- base64url: (0, import_base64url2.base64urlEncode)(new Uint8Array(bytes)),
213
+ parsed: (0, import_base64url2.base64urlEncode)(new Uint8Array(bytes)),
224
214
  originalFormat: "base64"
225
215
  };
226
216
  } catch {
@@ -229,50 +219,77 @@ function parseSolanaTransactionToBase64Url(transaction) {
229
219
  }
230
220
  throw new Error("Unsupported Solana transaction format");
231
221
  }
232
- function parseEVMTransactionToBase64Url(transaction) {
233
- if (transaction && typeof transaction === "object" && (transaction.to || transaction.data)) {
234
- const bytes = new TextEncoder().encode(
235
- JSON.stringify(transaction, (_key, value) => typeof value === "bigint" ? value.toString() : value)
236
- );
222
+ function parseEVMTransactionToHex(transaction) {
223
+ if (typeof transaction === "string" && transaction.startsWith("0x")) {
237
224
  return {
238
- base64url: (0, import_base64url2.base64urlEncode)(bytes),
239
- originalFormat: "viem"
225
+ parsed: transaction,
226
+ originalFormat: "hex"
240
227
  };
241
228
  }
242
229
  if (transaction?.serialize && typeof transaction.serialize === "function") {
243
230
  const serialized = transaction.serialize();
244
- const bytes = new Uint8Array(import_buffer2.Buffer.from(serialized.slice(2), "hex"));
231
+ const hex = serialized.startsWith("0x") ? serialized : "0x" + serialized;
245
232
  return {
246
- base64url: (0, import_base64url2.base64urlEncode)(bytes),
233
+ parsed: hex,
247
234
  originalFormat: "ethers"
248
235
  };
249
236
  }
250
237
  if (transaction instanceof Uint8Array) {
238
+ const hex = "0x" + import_buffer2.Buffer.from(transaction).toString("hex");
251
239
  return {
252
- base64url: (0, import_base64url2.base64urlEncode)(transaction),
240
+ parsed: hex,
253
241
  originalFormat: "bytes"
254
242
  };
255
243
  }
256
- if (typeof transaction === "string" && transaction.startsWith("0x")) {
257
- const bytes = new Uint8Array(import_buffer2.Buffer.from(transaction.slice(2), "hex"));
258
- return {
259
- base64url: (0, import_base64url2.base64urlEncode)(bytes),
260
- originalFormat: "hex"
261
- };
244
+ if (transaction && typeof transaction === "object" && (transaction.to || transaction.data || transaction.from)) {
245
+ try {
246
+ const { from, gas, ...txForSerialization } = transaction;
247
+ if (gas) {
248
+ txForSerialization.gasLimit = gas;
249
+ }
250
+ if (!txForSerialization.gasLimit) {
251
+ if (txForSerialization.to && txForSerialization.value && !txForSerialization.data) {
252
+ txForSerialization.gasLimit = "0x5208";
253
+ }
254
+ }
255
+ if (txForSerialization.to && typeof txForSerialization.to === "string") {
256
+ try {
257
+ txForSerialization.to = (0, import_ethers.getAddress)(txForSerialization.to);
258
+ } catch {
259
+ txForSerialization.to = txForSerialization.to.toLowerCase();
260
+ }
261
+ }
262
+ const serialized = import_ethers.Transaction.from(txForSerialization).unsignedSerialized;
263
+ const hex = serialized.startsWith("0x") ? serialized : "0x" + serialized;
264
+ return {
265
+ parsed: hex,
266
+ originalFormat: "json"
267
+ };
268
+ } catch (error) {
269
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
270
+ const txKeys = transaction ? Object.keys(transaction).join(", ") : "N/A";
271
+ const txValues = transaction ? JSON.stringify(transaction, null, 2) : "N/A";
272
+ throw new Error(
273
+ `Failed to RLP encode EVM transaction: ${errorMessage}.
274
+ Transaction keys: [${txKeys}].
275
+ Transaction: ${txValues}
276
+ Please ensure the transaction object includes required fields (to, value, chainId, gasLimit or gasPrice, etc.)`
277
+ );
278
+ }
262
279
  }
263
- throw new Error("Unsupported EVM transaction format");
280
+ throw new Error("Unsupported EVM transaction format. Expected hex string, bytes, or transaction object with 'to', 'data', or 'from' fields.");
264
281
  }
265
282
  async function parseSuiTransactionToBase64Url(transaction) {
266
283
  if (transaction?.serialize && typeof transaction.serialize === "function") {
267
284
  const serialized = transaction.serialize();
268
285
  return {
269
- base64url: (0, import_base64url2.base64urlEncode)(serialized),
286
+ parsed: (0, import_base64url2.base64urlEncode)(serialized),
270
287
  originalFormat: "sui-sdk"
271
288
  };
272
289
  }
273
290
  if (transaction instanceof Uint8Array) {
274
291
  return {
275
- base64url: (0, import_base64url2.base64urlEncode)(transaction),
292
+ parsed: (0, import_base64url2.base64urlEncode)(transaction),
276
293
  originalFormat: "bytes"
277
294
  };
278
295
  }
@@ -281,7 +298,7 @@ async function parseSuiTransactionToBase64Url(transaction) {
281
298
  if (built?.serialize && typeof built.serialize === "function") {
282
299
  const serialized = built.serialize();
283
300
  return {
284
- base64url: (0, import_base64url2.base64urlEncode)(serialized),
301
+ parsed: (0, import_base64url2.base64urlEncode)(serialized),
285
302
  originalFormat: "transaction-block"
286
303
  };
287
304
  }
@@ -292,20 +309,20 @@ function parseBitcoinTransactionToBase64Url(transaction) {
292
309
  if (transaction?.toBuffer && typeof transaction.toBuffer === "function") {
293
310
  const buffer = transaction.toBuffer();
294
311
  return {
295
- base64url: (0, import_base64url2.base64urlEncode)(new Uint8Array(buffer)),
312
+ parsed: (0, import_base64url2.base64urlEncode)(new Uint8Array(buffer)),
296
313
  originalFormat: "bitcoinjs-lib"
297
314
  };
298
315
  }
299
316
  if (transaction instanceof Uint8Array) {
300
317
  return {
301
- base64url: (0, import_base64url2.base64urlEncode)(transaction),
318
+ parsed: (0, import_base64url2.base64urlEncode)(transaction),
302
319
  originalFormat: "bytes"
303
320
  };
304
321
  }
305
322
  if (typeof transaction === "string") {
306
323
  const bytes = new Uint8Array(import_buffer2.Buffer.from(transaction, "hex"));
307
324
  return {
308
- base64url: (0, import_base64url2.base64urlEncode)(bytes),
325
+ parsed: (0, import_base64url2.base64urlEncode)(bytes),
309
326
  originalFormat: "hex"
310
327
  };
311
328
  }
@@ -322,10 +339,9 @@ function parseSolanaKitTransactionToSolanaWeb3js(transaction) {
322
339
  }
323
340
  // Annotate the CommonJS export names for ESM import in node:
324
341
  0 && (module.exports = {
325
- parseMessage,
326
342
  parseSignMessageResponse,
327
343
  parseSolanaKitTransactionToSolanaWeb3js,
328
344
  parseSolanaSignedTransaction,
329
- parseTransactionResponse,
330
- parseTransactionToBase64Url
345
+ parseToKmsTransaction,
346
+ parseTransactionResponse
331
347
  });
package/dist/index.mjs CHANGED
@@ -1,11 +1,13 @@
1
1
  // src/index.ts
2
- import { base64urlEncode, stringToBase64url } from "@phantom/base64url";
2
+ import { base64urlEncode } from "@phantom/base64url";
3
3
  import { getTransactionEncoder } from "@solana/transactions";
4
4
  import { Buffer as Buffer2 } from "buffer";
5
+ import { Transaction as EthersTransaction, getAddress } from "ethers";
5
6
 
6
7
  // src/response-parsers.ts
7
8
  import { base64urlDecode } from "@phantom/base64url";
8
9
  import { getExplorerUrl } from "@phantom/constants";
10
+ import { isEthereumChain } from "@phantom/utils";
9
11
  import { Transaction, VersionedTransaction } from "@solana/web3.js";
10
12
  import bs58 from "bs58";
11
13
  import { Buffer } from "buffer";
@@ -30,15 +32,24 @@ function parseSignMessageResponse(base64Response, networkId) {
30
32
  }
31
33
  }
32
34
  function parseTransactionResponse(base64RawTransaction, networkId, hash) {
35
+ let rawTransaction = base64RawTransaction;
36
+ if (isEthereumChain(networkId)) {
37
+ try {
38
+ const txBytes = base64urlDecode(base64RawTransaction);
39
+ rawTransaction = "0x" + Buffer.from(txBytes).toString("hex");
40
+ } catch (error) {
41
+ rawTransaction = base64RawTransaction.startsWith("0x") ? base64RawTransaction : "0x" + base64RawTransaction;
42
+ }
43
+ }
33
44
  if (hash) {
34
45
  return {
35
46
  hash,
36
- rawTransaction: base64RawTransaction,
47
+ rawTransaction,
37
48
  blockExplorer: getExplorerUrl(networkId, "transaction", hash)
38
49
  };
39
50
  } else {
40
51
  return {
41
- rawTransaction: base64RawTransaction
52
+ rawTransaction
42
53
  };
43
54
  }
44
55
  }
@@ -58,27 +69,12 @@ function parseSolanaSignatureResponse(base64Response) {
58
69
  }
59
70
  }
60
71
  function parseEVMSignatureResponse(base64Response) {
61
- try {
62
- const signatureBytes = base64urlDecode(base64Response);
63
- if (signatureBytes.length === 65) {
64
- const recoveryId = signatureBytes[64];
65
- if (recoveryId === 0 || recoveryId === 1) {
66
- signatureBytes[64] = recoveryId + 27;
67
- }
68
- }
69
- const signature = "0x" + Buffer.from(signatureBytes).toString("hex");
70
- return {
71
- signature,
72
- rawSignature: base64Response
73
- // Note: Most block explorers don't have direct signature lookup, only transaction lookup
74
- };
75
- } catch (error) {
76
- const signature = base64Response.startsWith("0x") ? base64Response : "0x" + base64Response;
77
- return {
78
- signature,
79
- rawSignature: base64Response
80
- };
81
- }
72
+ const signatureBytes = base64urlDecode(base64Response);
73
+ const signature = "0x" + Buffer.from(signatureBytes).toString("hex");
74
+ return {
75
+ signature,
76
+ rawSignature: base64Response
77
+ };
82
78
  }
83
79
  function parseSuiSignatureResponse(base64Response) {
84
80
  try {
@@ -129,12 +125,7 @@ function parseSolanaSignedTransaction(base64RawTransaction) {
129
125
  }
130
126
 
131
127
  // src/index.ts
132
- function parseMessage(message) {
133
- return {
134
- base64url: stringToBase64url(message)
135
- };
136
- }
137
- async function parseTransactionToBase64Url(transaction, networkId) {
128
+ async function parseToKmsTransaction(transaction, networkId) {
138
129
  const networkPrefix = networkId.split(":")[0].toLowerCase();
139
130
  switch (networkPrefix) {
140
131
  case "solana":
@@ -145,7 +136,7 @@ async function parseTransactionToBase64Url(transaction, networkId) {
145
136
  case "optimism":
146
137
  case "arbitrum":
147
138
  case "base":
148
- return parseEVMTransactionToBase64Url(transaction);
139
+ return parseEVMTransactionToHex(transaction);
149
140
  case "sui":
150
141
  return await parseSuiTransactionToBase64Url(transaction);
151
142
  case "bitcoin":
@@ -157,7 +148,7 @@ async function parseTransactionToBase64Url(transaction, networkId) {
157
148
  function parseSolanaTransactionToBase64Url(transaction) {
158
149
  if (transaction?.messageBytes != null) {
159
150
  return {
160
- base64url: base64urlEncode(transaction.messageBytes),
151
+ parsed: base64urlEncode(transaction.messageBytes),
161
152
  originalFormat: "@solana/kit"
162
153
  };
163
154
  }
@@ -167,13 +158,13 @@ function parseSolanaTransactionToBase64Url(transaction) {
167
158
  verifySignatures: false
168
159
  });
169
160
  return {
170
- base64url: base64urlEncode(serialized),
161
+ parsed: base64urlEncode(serialized),
171
162
  originalFormat: "@solana/web3.js"
172
163
  };
173
164
  }
174
165
  if (transaction instanceof Uint8Array) {
175
166
  return {
176
- base64url: base64urlEncode(transaction),
167
+ parsed: base64urlEncode(transaction),
177
168
  originalFormat: "bytes"
178
169
  };
179
170
  }
@@ -181,7 +172,7 @@ function parseSolanaTransactionToBase64Url(transaction) {
181
172
  try {
182
173
  const bytes = Buffer2.from(transaction, "base64");
183
174
  return {
184
- base64url: base64urlEncode(new Uint8Array(bytes)),
175
+ parsed: base64urlEncode(new Uint8Array(bytes)),
185
176
  originalFormat: "base64"
186
177
  };
187
178
  } catch {
@@ -190,50 +181,77 @@ function parseSolanaTransactionToBase64Url(transaction) {
190
181
  }
191
182
  throw new Error("Unsupported Solana transaction format");
192
183
  }
193
- function parseEVMTransactionToBase64Url(transaction) {
194
- if (transaction && typeof transaction === "object" && (transaction.to || transaction.data)) {
195
- const bytes = new TextEncoder().encode(
196
- JSON.stringify(transaction, (_key, value) => typeof value === "bigint" ? value.toString() : value)
197
- );
184
+ function parseEVMTransactionToHex(transaction) {
185
+ if (typeof transaction === "string" && transaction.startsWith("0x")) {
198
186
  return {
199
- base64url: base64urlEncode(bytes),
200
- originalFormat: "viem"
187
+ parsed: transaction,
188
+ originalFormat: "hex"
201
189
  };
202
190
  }
203
191
  if (transaction?.serialize && typeof transaction.serialize === "function") {
204
192
  const serialized = transaction.serialize();
205
- const bytes = new Uint8Array(Buffer2.from(serialized.slice(2), "hex"));
193
+ const hex = serialized.startsWith("0x") ? serialized : "0x" + serialized;
206
194
  return {
207
- base64url: base64urlEncode(bytes),
195
+ parsed: hex,
208
196
  originalFormat: "ethers"
209
197
  };
210
198
  }
211
199
  if (transaction instanceof Uint8Array) {
200
+ const hex = "0x" + Buffer2.from(transaction).toString("hex");
212
201
  return {
213
- base64url: base64urlEncode(transaction),
202
+ parsed: hex,
214
203
  originalFormat: "bytes"
215
204
  };
216
205
  }
217
- if (typeof transaction === "string" && transaction.startsWith("0x")) {
218
- const bytes = new Uint8Array(Buffer2.from(transaction.slice(2), "hex"));
219
- return {
220
- base64url: base64urlEncode(bytes),
221
- originalFormat: "hex"
222
- };
206
+ if (transaction && typeof transaction === "object" && (transaction.to || transaction.data || transaction.from)) {
207
+ try {
208
+ const { from, gas, ...txForSerialization } = transaction;
209
+ if (gas) {
210
+ txForSerialization.gasLimit = gas;
211
+ }
212
+ if (!txForSerialization.gasLimit) {
213
+ if (txForSerialization.to && txForSerialization.value && !txForSerialization.data) {
214
+ txForSerialization.gasLimit = "0x5208";
215
+ }
216
+ }
217
+ if (txForSerialization.to && typeof txForSerialization.to === "string") {
218
+ try {
219
+ txForSerialization.to = getAddress(txForSerialization.to);
220
+ } catch {
221
+ txForSerialization.to = txForSerialization.to.toLowerCase();
222
+ }
223
+ }
224
+ const serialized = EthersTransaction.from(txForSerialization).unsignedSerialized;
225
+ const hex = serialized.startsWith("0x") ? serialized : "0x" + serialized;
226
+ return {
227
+ parsed: hex,
228
+ originalFormat: "json"
229
+ };
230
+ } catch (error) {
231
+ const errorMessage = error instanceof Error ? error.message : "Unknown error";
232
+ const txKeys = transaction ? Object.keys(transaction).join(", ") : "N/A";
233
+ const txValues = transaction ? JSON.stringify(transaction, null, 2) : "N/A";
234
+ throw new Error(
235
+ `Failed to RLP encode EVM transaction: ${errorMessage}.
236
+ Transaction keys: [${txKeys}].
237
+ Transaction: ${txValues}
238
+ Please ensure the transaction object includes required fields (to, value, chainId, gasLimit or gasPrice, etc.)`
239
+ );
240
+ }
223
241
  }
224
- throw new Error("Unsupported EVM transaction format");
242
+ throw new Error("Unsupported EVM transaction format. Expected hex string, bytes, or transaction object with 'to', 'data', or 'from' fields.");
225
243
  }
226
244
  async function parseSuiTransactionToBase64Url(transaction) {
227
245
  if (transaction?.serialize && typeof transaction.serialize === "function") {
228
246
  const serialized = transaction.serialize();
229
247
  return {
230
- base64url: base64urlEncode(serialized),
248
+ parsed: base64urlEncode(serialized),
231
249
  originalFormat: "sui-sdk"
232
250
  };
233
251
  }
234
252
  if (transaction instanceof Uint8Array) {
235
253
  return {
236
- base64url: base64urlEncode(transaction),
254
+ parsed: base64urlEncode(transaction),
237
255
  originalFormat: "bytes"
238
256
  };
239
257
  }
@@ -242,7 +260,7 @@ async function parseSuiTransactionToBase64Url(transaction) {
242
260
  if (built?.serialize && typeof built.serialize === "function") {
243
261
  const serialized = built.serialize();
244
262
  return {
245
- base64url: base64urlEncode(serialized),
263
+ parsed: base64urlEncode(serialized),
246
264
  originalFormat: "transaction-block"
247
265
  };
248
266
  }
@@ -253,20 +271,20 @@ function parseBitcoinTransactionToBase64Url(transaction) {
253
271
  if (transaction?.toBuffer && typeof transaction.toBuffer === "function") {
254
272
  const buffer = transaction.toBuffer();
255
273
  return {
256
- base64url: base64urlEncode(new Uint8Array(buffer)),
274
+ parsed: base64urlEncode(new Uint8Array(buffer)),
257
275
  originalFormat: "bitcoinjs-lib"
258
276
  };
259
277
  }
260
278
  if (transaction instanceof Uint8Array) {
261
279
  return {
262
- base64url: base64urlEncode(transaction),
280
+ parsed: base64urlEncode(transaction),
263
281
  originalFormat: "bytes"
264
282
  };
265
283
  }
266
284
  if (typeof transaction === "string") {
267
285
  const bytes = new Uint8Array(Buffer2.from(transaction, "hex"));
268
286
  return {
269
- base64url: base64urlEncode(bytes),
287
+ parsed: base64urlEncode(bytes),
270
288
  originalFormat: "hex"
271
289
  };
272
290
  }
@@ -282,10 +300,9 @@ function parseSolanaKitTransactionToSolanaWeb3js(transaction) {
282
300
  return fakeVersioned;
283
301
  }
284
302
  export {
285
- parseMessage,
286
303
  parseSignMessageResponse,
287
304
  parseSolanaKitTransactionToSolanaWeb3js,
288
305
  parseSolanaSignedTransaction,
289
- parseTransactionResponse,
290
- parseTransactionToBase64Url
306
+ parseToKmsTransaction,
307
+ parseTransactionResponse
291
308
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/parsers",
3
- "version": "1.0.0-beta.7",
3
+ "version": "1.0.0-beta.9",
4
4
  "description": "Transaction and message parsers for Phantom Wallet SDK",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -29,18 +29,19 @@
29
29
  "prettier": "prettier --write \"src/**/*.{ts}\""
30
30
  },
31
31
  "dependencies": {
32
- "@phantom/base64url": "^1.0.0-beta.7",
33
- "@phantom/constants": "^1.0.0-beta.7",
34
- "@phantom/sdk-types": "^1.0.0-beta.7",
32
+ "@phantom/base64url": "^1.0.0-beta.9",
33
+ "@phantom/constants": "^1.0.0-beta.9",
34
+ "@phantom/sdk-types": "^1.0.0-beta.9",
35
+ "@phantom/utils": "^1.0.0-beta.21",
35
36
  "@solana/transactions": "^2.0.0",
36
37
  "@solana/web3.js": "^1.95.0",
37
38
  "bs58": "^6.0.0",
38
- "buffer": "^6.0.3"
39
+ "buffer": "^6.0.3",
40
+ "ethers": "^6.0.0"
39
41
  },
40
42
  "optionalDependencies": {
41
43
  "@mysten/sui.js": "^0.50.0",
42
44
  "bitcoinjs-lib": "^6.1.0",
43
- "ethers": "^6.0.0",
44
45
  "viem": "^2.0.0"
45
46
  },
46
47
  "devDependencies": {