@phantom/parsers 1.0.0-beta.6 → 1.0.0-beta.8

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,24 +30,25 @@ 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
- var import_constants = require("@phantom/constants");
47
46
  var import_base64url = require("@phantom/base64url");
48
- var import_buffer = require("buffer");
49
- var import_bs58 = __toESM(require("bs58"));
47
+ var import_constants = require("@phantom/constants");
48
+ var import_utils = require("@phantom/utils");
50
49
  var import_web3 = require("@solana/web3.js");
50
+ var import_bs58 = __toESM(require("bs58"));
51
+ var import_buffer = require("buffer");
51
52
  function parseSignMessageResponse(base64Response, networkId) {
52
53
  const networkPrefix = networkId.split(":")[0].toLowerCase();
53
54
  switch (networkPrefix) {
@@ -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,21 +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
- const signature = "0x" + import_buffer.Buffer.from(signatureBytes).toString("hex");
103
- return {
104
- signature,
105
- rawSignature: base64Response
106
- // Note: Most block explorers don't have direct signature lookup, only transaction lookup
107
- };
108
- } catch (error) {
109
- const signature = base64Response.startsWith("0x") ? base64Response : "0x" + base64Response;
110
- return {
111
- signature,
112
- rawSignature: base64Response
113
- };
114
- }
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
+ };
115
116
  }
116
117
  function parseSuiSignatureResponse(base64Response) {
117
118
  try {
@@ -159,16 +160,10 @@ function parseSolanaSignedTransaction(base64RawTransaction) {
159
160
  } catch (error) {
160
161
  return null;
161
162
  }
162
- ;
163
163
  }
164
164
 
165
165
  // src/index.ts
166
- function parseMessage(message) {
167
- return {
168
- base64url: (0, import_base64url2.stringToBase64url)(message)
169
- };
170
- }
171
- async function parseTransactionToBase64Url(transaction, networkId) {
166
+ async function parseToKmsTransaction(transaction, networkId) {
172
167
  const networkPrefix = networkId.split(":")[0].toLowerCase();
173
168
  switch (networkPrefix) {
174
169
  case "solana":
@@ -179,7 +174,7 @@ async function parseTransactionToBase64Url(transaction, networkId) {
179
174
  case "optimism":
180
175
  case "arbitrum":
181
176
  case "base":
182
- return parseEVMTransactionToBase64Url(transaction);
177
+ return parseEVMTransactionToHex(transaction);
183
178
  case "sui":
184
179
  return await parseSuiTransactionToBase64Url(transaction);
185
180
  case "bitcoin":
@@ -191,7 +186,7 @@ async function parseTransactionToBase64Url(transaction, networkId) {
191
186
  function parseSolanaTransactionToBase64Url(transaction) {
192
187
  if (transaction?.messageBytes != null) {
193
188
  return {
194
- base64url: (0, import_base64url2.base64urlEncode)(transaction.messageBytes),
189
+ parsed: (0, import_base64url2.base64urlEncode)(transaction.messageBytes),
195
190
  originalFormat: "@solana/kit"
196
191
  };
197
192
  }
@@ -201,13 +196,13 @@ function parseSolanaTransactionToBase64Url(transaction) {
201
196
  verifySignatures: false
202
197
  });
203
198
  return {
204
- base64url: (0, import_base64url2.base64urlEncode)(serialized),
199
+ parsed: (0, import_base64url2.base64urlEncode)(serialized),
205
200
  originalFormat: "@solana/web3.js"
206
201
  };
207
202
  }
208
203
  if (transaction instanceof Uint8Array) {
209
204
  return {
210
- base64url: (0, import_base64url2.base64urlEncode)(transaction),
205
+ parsed: (0, import_base64url2.base64urlEncode)(transaction),
211
206
  originalFormat: "bytes"
212
207
  };
213
208
  }
@@ -215,7 +210,7 @@ function parseSolanaTransactionToBase64Url(transaction) {
215
210
  try {
216
211
  const bytes = import_buffer2.Buffer.from(transaction, "base64");
217
212
  return {
218
- base64url: (0, import_base64url2.base64urlEncode)(new Uint8Array(bytes)),
213
+ parsed: (0, import_base64url2.base64urlEncode)(new Uint8Array(bytes)),
219
214
  originalFormat: "base64"
220
215
  };
221
216
  } catch {
@@ -224,50 +219,77 @@ function parseSolanaTransactionToBase64Url(transaction) {
224
219
  }
225
220
  throw new Error("Unsupported Solana transaction format");
226
221
  }
227
- function parseEVMTransactionToBase64Url(transaction) {
228
- if (transaction && typeof transaction === "object" && (transaction.to || transaction.data)) {
229
- const bytes = new TextEncoder().encode(
230
- JSON.stringify(transaction, (_key, value) => typeof value === "bigint" ? value.toString() : value)
231
- );
222
+ function parseEVMTransactionToHex(transaction) {
223
+ if (typeof transaction === "string" && transaction.startsWith("0x")) {
232
224
  return {
233
- base64url: (0, import_base64url2.base64urlEncode)(bytes),
234
- originalFormat: "viem"
225
+ parsed: transaction,
226
+ originalFormat: "hex"
235
227
  };
236
228
  }
237
229
  if (transaction?.serialize && typeof transaction.serialize === "function") {
238
230
  const serialized = transaction.serialize();
239
- const bytes = new Uint8Array(import_buffer2.Buffer.from(serialized.slice(2), "hex"));
231
+ const hex = serialized.startsWith("0x") ? serialized : "0x" + serialized;
240
232
  return {
241
- base64url: (0, import_base64url2.base64urlEncode)(bytes),
233
+ parsed: hex,
242
234
  originalFormat: "ethers"
243
235
  };
244
236
  }
245
237
  if (transaction instanceof Uint8Array) {
238
+ const hex = "0x" + import_buffer2.Buffer.from(transaction).toString("hex");
246
239
  return {
247
- base64url: (0, import_base64url2.base64urlEncode)(transaction),
240
+ parsed: hex,
248
241
  originalFormat: "bytes"
249
242
  };
250
243
  }
251
- if (typeof transaction === "string" && transaction.startsWith("0x")) {
252
- const bytes = new Uint8Array(import_buffer2.Buffer.from(transaction.slice(2), "hex"));
253
- return {
254
- base64url: (0, import_base64url2.base64urlEncode)(bytes),
255
- originalFormat: "hex"
256
- };
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
+ }
257
279
  }
258
- 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.");
259
281
  }
260
282
  async function parseSuiTransactionToBase64Url(transaction) {
261
283
  if (transaction?.serialize && typeof transaction.serialize === "function") {
262
284
  const serialized = transaction.serialize();
263
285
  return {
264
- base64url: (0, import_base64url2.base64urlEncode)(serialized),
286
+ parsed: (0, import_base64url2.base64urlEncode)(serialized),
265
287
  originalFormat: "sui-sdk"
266
288
  };
267
289
  }
268
290
  if (transaction instanceof Uint8Array) {
269
291
  return {
270
- base64url: (0, import_base64url2.base64urlEncode)(transaction),
292
+ parsed: (0, import_base64url2.base64urlEncode)(transaction),
271
293
  originalFormat: "bytes"
272
294
  };
273
295
  }
@@ -276,7 +298,7 @@ async function parseSuiTransactionToBase64Url(transaction) {
276
298
  if (built?.serialize && typeof built.serialize === "function") {
277
299
  const serialized = built.serialize();
278
300
  return {
279
- base64url: (0, import_base64url2.base64urlEncode)(serialized),
301
+ parsed: (0, import_base64url2.base64urlEncode)(serialized),
280
302
  originalFormat: "transaction-block"
281
303
  };
282
304
  }
@@ -287,20 +309,20 @@ function parseBitcoinTransactionToBase64Url(transaction) {
287
309
  if (transaction?.toBuffer && typeof transaction.toBuffer === "function") {
288
310
  const buffer = transaction.toBuffer();
289
311
  return {
290
- base64url: (0, import_base64url2.base64urlEncode)(new Uint8Array(buffer)),
312
+ parsed: (0, import_base64url2.base64urlEncode)(new Uint8Array(buffer)),
291
313
  originalFormat: "bitcoinjs-lib"
292
314
  };
293
315
  }
294
316
  if (transaction instanceof Uint8Array) {
295
317
  return {
296
- base64url: (0, import_base64url2.base64urlEncode)(transaction),
318
+ parsed: (0, import_base64url2.base64urlEncode)(transaction),
297
319
  originalFormat: "bytes"
298
320
  };
299
321
  }
300
322
  if (typeof transaction === "string") {
301
323
  const bytes = new Uint8Array(import_buffer2.Buffer.from(transaction, "hex"));
302
324
  return {
303
- base64url: (0, import_base64url2.base64urlEncode)(bytes),
325
+ parsed: (0, import_base64url2.base64urlEncode)(bytes),
304
326
  originalFormat: "hex"
305
327
  };
306
328
  }
@@ -317,10 +339,9 @@ function parseSolanaKitTransactionToSolanaWeb3js(transaction) {
317
339
  }
318
340
  // Annotate the CommonJS export names for ESM import in node:
319
341
  0 && (module.exports = {
320
- parseMessage,
321
342
  parseSignMessageResponse,
322
343
  parseSolanaKitTransactionToSolanaWeb3js,
323
344
  parseSolanaSignedTransaction,
324
- parseTransactionResponse,
325
- parseTransactionToBase64Url
345
+ parseToKmsTransaction,
346
+ parseTransactionResponse
326
347
  });
package/dist/index.mjs CHANGED
@@ -1,14 +1,16 @@
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
- import { getExplorerUrl } from "@phantom/constants";
8
8
  import { base64urlDecode } from "@phantom/base64url";
9
- import { Buffer } from "buffer";
10
- import bs58 from "bs58";
9
+ import { getExplorerUrl } from "@phantom/constants";
10
+ import { isEthereumChain } from "@phantom/utils";
11
11
  import { Transaction, VersionedTransaction } from "@solana/web3.js";
12
+ import bs58 from "bs58";
13
+ import { Buffer } from "buffer";
12
14
  function parseSignMessageResponse(base64Response, networkId) {
13
15
  const networkPrefix = networkId.split(":")[0].toLowerCase();
14
16
  switch (networkPrefix) {
@@ -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,21 +69,12 @@ function parseSolanaSignatureResponse(base64Response) {
58
69
  }
59
70
  }
60
71
  function parseEVMSignatureResponse(base64Response) {
61
- try {
62
- const signatureBytes = base64urlDecode(base64Response);
63
- const signature = "0x" + Buffer.from(signatureBytes).toString("hex");
64
- return {
65
- signature,
66
- rawSignature: base64Response
67
- // Note: Most block explorers don't have direct signature lookup, only transaction lookup
68
- };
69
- } catch (error) {
70
- const signature = base64Response.startsWith("0x") ? base64Response : "0x" + base64Response;
71
- return {
72
- signature,
73
- rawSignature: base64Response
74
- };
75
- }
72
+ const signatureBytes = base64urlDecode(base64Response);
73
+ const signature = "0x" + Buffer.from(signatureBytes).toString("hex");
74
+ return {
75
+ signature,
76
+ rawSignature: base64Response
77
+ };
76
78
  }
77
79
  function parseSuiSignatureResponse(base64Response) {
78
80
  try {
@@ -120,16 +122,10 @@ function parseSolanaSignedTransaction(base64RawTransaction) {
120
122
  } catch (error) {
121
123
  return null;
122
124
  }
123
- ;
124
125
  }
125
126
 
126
127
  // src/index.ts
127
- function parseMessage(message) {
128
- return {
129
- base64url: stringToBase64url(message)
130
- };
131
- }
132
- async function parseTransactionToBase64Url(transaction, networkId) {
128
+ async function parseToKmsTransaction(transaction, networkId) {
133
129
  const networkPrefix = networkId.split(":")[0].toLowerCase();
134
130
  switch (networkPrefix) {
135
131
  case "solana":
@@ -140,7 +136,7 @@ async function parseTransactionToBase64Url(transaction, networkId) {
140
136
  case "optimism":
141
137
  case "arbitrum":
142
138
  case "base":
143
- return parseEVMTransactionToBase64Url(transaction);
139
+ return parseEVMTransactionToHex(transaction);
144
140
  case "sui":
145
141
  return await parseSuiTransactionToBase64Url(transaction);
146
142
  case "bitcoin":
@@ -152,7 +148,7 @@ async function parseTransactionToBase64Url(transaction, networkId) {
152
148
  function parseSolanaTransactionToBase64Url(transaction) {
153
149
  if (transaction?.messageBytes != null) {
154
150
  return {
155
- base64url: base64urlEncode(transaction.messageBytes),
151
+ parsed: base64urlEncode(transaction.messageBytes),
156
152
  originalFormat: "@solana/kit"
157
153
  };
158
154
  }
@@ -162,13 +158,13 @@ function parseSolanaTransactionToBase64Url(transaction) {
162
158
  verifySignatures: false
163
159
  });
164
160
  return {
165
- base64url: base64urlEncode(serialized),
161
+ parsed: base64urlEncode(serialized),
166
162
  originalFormat: "@solana/web3.js"
167
163
  };
168
164
  }
169
165
  if (transaction instanceof Uint8Array) {
170
166
  return {
171
- base64url: base64urlEncode(transaction),
167
+ parsed: base64urlEncode(transaction),
172
168
  originalFormat: "bytes"
173
169
  };
174
170
  }
@@ -176,7 +172,7 @@ function parseSolanaTransactionToBase64Url(transaction) {
176
172
  try {
177
173
  const bytes = Buffer2.from(transaction, "base64");
178
174
  return {
179
- base64url: base64urlEncode(new Uint8Array(bytes)),
175
+ parsed: base64urlEncode(new Uint8Array(bytes)),
180
176
  originalFormat: "base64"
181
177
  };
182
178
  } catch {
@@ -185,50 +181,77 @@ function parseSolanaTransactionToBase64Url(transaction) {
185
181
  }
186
182
  throw new Error("Unsupported Solana transaction format");
187
183
  }
188
- function parseEVMTransactionToBase64Url(transaction) {
189
- if (transaction && typeof transaction === "object" && (transaction.to || transaction.data)) {
190
- const bytes = new TextEncoder().encode(
191
- JSON.stringify(transaction, (_key, value) => typeof value === "bigint" ? value.toString() : value)
192
- );
184
+ function parseEVMTransactionToHex(transaction) {
185
+ if (typeof transaction === "string" && transaction.startsWith("0x")) {
193
186
  return {
194
- base64url: base64urlEncode(bytes),
195
- originalFormat: "viem"
187
+ parsed: transaction,
188
+ originalFormat: "hex"
196
189
  };
197
190
  }
198
191
  if (transaction?.serialize && typeof transaction.serialize === "function") {
199
192
  const serialized = transaction.serialize();
200
- const bytes = new Uint8Array(Buffer2.from(serialized.slice(2), "hex"));
193
+ const hex = serialized.startsWith("0x") ? serialized : "0x" + serialized;
201
194
  return {
202
- base64url: base64urlEncode(bytes),
195
+ parsed: hex,
203
196
  originalFormat: "ethers"
204
197
  };
205
198
  }
206
199
  if (transaction instanceof Uint8Array) {
200
+ const hex = "0x" + Buffer2.from(transaction).toString("hex");
207
201
  return {
208
- base64url: base64urlEncode(transaction),
202
+ parsed: hex,
209
203
  originalFormat: "bytes"
210
204
  };
211
205
  }
212
- if (typeof transaction === "string" && transaction.startsWith("0x")) {
213
- const bytes = new Uint8Array(Buffer2.from(transaction.slice(2), "hex"));
214
- return {
215
- base64url: base64urlEncode(bytes),
216
- originalFormat: "hex"
217
- };
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
+ }
218
241
  }
219
- 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.");
220
243
  }
221
244
  async function parseSuiTransactionToBase64Url(transaction) {
222
245
  if (transaction?.serialize && typeof transaction.serialize === "function") {
223
246
  const serialized = transaction.serialize();
224
247
  return {
225
- base64url: base64urlEncode(serialized),
248
+ parsed: base64urlEncode(serialized),
226
249
  originalFormat: "sui-sdk"
227
250
  };
228
251
  }
229
252
  if (transaction instanceof Uint8Array) {
230
253
  return {
231
- base64url: base64urlEncode(transaction),
254
+ parsed: base64urlEncode(transaction),
232
255
  originalFormat: "bytes"
233
256
  };
234
257
  }
@@ -237,7 +260,7 @@ async function parseSuiTransactionToBase64Url(transaction) {
237
260
  if (built?.serialize && typeof built.serialize === "function") {
238
261
  const serialized = built.serialize();
239
262
  return {
240
- base64url: base64urlEncode(serialized),
263
+ parsed: base64urlEncode(serialized),
241
264
  originalFormat: "transaction-block"
242
265
  };
243
266
  }
@@ -248,20 +271,20 @@ function parseBitcoinTransactionToBase64Url(transaction) {
248
271
  if (transaction?.toBuffer && typeof transaction.toBuffer === "function") {
249
272
  const buffer = transaction.toBuffer();
250
273
  return {
251
- base64url: base64urlEncode(new Uint8Array(buffer)),
274
+ parsed: base64urlEncode(new Uint8Array(buffer)),
252
275
  originalFormat: "bitcoinjs-lib"
253
276
  };
254
277
  }
255
278
  if (transaction instanceof Uint8Array) {
256
279
  return {
257
- base64url: base64urlEncode(transaction),
280
+ parsed: base64urlEncode(transaction),
258
281
  originalFormat: "bytes"
259
282
  };
260
283
  }
261
284
  if (typeof transaction === "string") {
262
285
  const bytes = new Uint8Array(Buffer2.from(transaction, "hex"));
263
286
  return {
264
- base64url: base64urlEncode(bytes),
287
+ parsed: base64urlEncode(bytes),
265
288
  originalFormat: "hex"
266
289
  };
267
290
  }
@@ -277,10 +300,9 @@ function parseSolanaKitTransactionToSolanaWeb3js(transaction) {
277
300
  return fakeVersioned;
278
301
  }
279
302
  export {
280
- parseMessage,
281
303
  parseSignMessageResponse,
282
304
  parseSolanaKitTransactionToSolanaWeb3js,
283
305
  parseSolanaSignedTransaction,
284
- parseTransactionResponse,
285
- parseTransactionToBase64Url
306
+ parseToKmsTransaction,
307
+ parseTransactionResponse
286
308
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/parsers",
3
- "version": "1.0.0-beta.6",
3
+ "version": "1.0.0-beta.8",
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.6",
33
- "@phantom/constants": "^1.0.0-beta.6",
34
- "@phantom/sdk-types": "^1.0.0-beta.6",
32
+ "@phantom/base64url": "^1.0.0-beta.8",
33
+ "@phantom/constants": "^1.0.0-beta.8",
34
+ "@phantom/sdk-types": "^1.0.0-beta.8",
35
+ "@phantom/utils": "^1.0.0-beta.19",
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": {