@phantom/parsers 0.0.4 → 0.0.6

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
@@ -169,6 +169,10 @@ The parsers automatically detect the input format and handle conversion appropri
169
169
  - **Hex strings** - "0x"-prefixed hex-encoded transaction data
170
170
  - **Base64/Base64url** - Already encoded transaction data
171
171
 
172
+ ## Cross-Platform Compatibility
173
+
174
+ The parsers package is designed to work across different JavaScript environments including browsers, Node.js, and React Native. The package gracefully handles missing dependencies and provides consistent parsing functionality across all supported platforms.
175
+
172
176
  ## Error Handling
173
177
 
174
178
  The parsers will throw descriptive errors for:
@@ -220,8 +224,28 @@ yarn build
220
224
 
221
225
  # Run tests
222
226
  yarn test
227
+
228
+ # Run integration tests (requires RPC access)
229
+ yarn test:integration
223
230
  ```
224
231
 
232
+ ### Integration Tests
233
+
234
+ The package includes comprehensive integration tests that create real transactions using actual Solana libraries:
235
+
236
+ - **VersionedTransaction** parsing with `@solana/web3.js`
237
+ - **Legacy Transaction** parsing with `@solana/web3.js`
238
+ - **@solana/kit** transaction parsing
239
+ - Error handling and network resilience
240
+
241
+ To run integration tests:
242
+
243
+ 1. Copy `.env.example` to `.env`
244
+ 2. Set `SOLANA_RPC_URL` to your preferred Solana RPC endpoint
245
+ 3. Run `yarn test:integration`
246
+
247
+ **Note**: Integration tests make real network calls to fetch recent blockhashes but only create local test transactions (no funds required).
248
+
225
249
  ## License
226
250
 
227
251
  MIT License - see LICENSE file for details.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,28 @@
1
- import { NetworkId } from '@phantom/client';
1
+ import { NetworkId } from '@phantom/constants';
2
+
3
+ /**
4
+ * Chain-specific transaction and message response parsing
5
+ * This module contains the specific parsing logic for each blockchain network
6
+ */
7
+
8
+ interface ParsedSignatureResult {
9
+ signature: string;
10
+ rawSignature: string;
11
+ blockExplorer?: string;
12
+ }
13
+ interface ParsedTransactionResult {
14
+ hash?: string;
15
+ rawTransaction: string;
16
+ blockExplorer?: string;
17
+ }
18
+ /**
19
+ * Parse a signed message response from base64 to human-readable format
20
+ */
21
+ declare function parseSignMessageResponse(base64Response: string, networkId: NetworkId): ParsedSignatureResult;
22
+ /**
23
+ * Parse a transaction response from base64 rawTransaction to extract hash
24
+ */
25
+ declare function parseTransactionResponse(base64RawTransaction: string, networkId: NetworkId, hash?: string): ParsedTransactionResult;
2
26
 
3
27
  interface ParsedTransaction {
4
28
  base64url: string;
@@ -7,6 +31,7 @@ interface ParsedTransaction {
7
31
  interface ParsedMessage {
8
32
  base64url: string;
9
33
  }
34
+
10
35
  /**
11
36
  * Parse a message to base64url format for the client
12
37
  */
@@ -16,4 +41,4 @@ declare function parseMessage(message: string): ParsedMessage;
16
41
  */
17
42
  declare function parseTransaction(transaction: any, networkId: NetworkId): Promise<ParsedTransaction>;
18
43
 
19
- export { ParsedMessage, ParsedTransaction, parseMessage, parseTransaction };
44
+ export { ParsedMessage, ParsedSignatureResult, ParsedTransaction, ParsedTransactionResult, parseMessage, parseSignMessageResponse, parseTransaction, parseTransactionResponse };
package/dist/index.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,20 +17,133 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/index.ts
21
31
  var src_exports = {};
22
32
  __export(src_exports, {
23
33
  parseMessage: () => parseMessage,
24
- parseTransaction: () => parseTransaction
34
+ parseSignMessageResponse: () => parseSignMessageResponse,
35
+ parseTransaction: () => parseTransaction,
36
+ parseTransactionResponse: () => parseTransactionResponse
25
37
  });
26
38
  module.exports = __toCommonJS(src_exports);
39
+ var import_base64url2 = require("@phantom/base64url");
40
+ var import_buffer2 = require("buffer");
41
+
42
+ // src/response-parsers.ts
43
+ var import_constants = require("@phantom/constants");
27
44
  var import_base64url = require("@phantom/base64url");
28
45
  var import_buffer = require("buffer");
46
+ var import_bs58 = __toESM(require("bs58"));
47
+ function parseSignMessageResponse(base64Response, networkId) {
48
+ const networkPrefix = networkId.split(":")[0].toLowerCase();
49
+ switch (networkPrefix) {
50
+ case "solana":
51
+ return parseSolanaSignatureResponse(base64Response);
52
+ case "eip155":
53
+ case "ethereum":
54
+ return parseEVMSignatureResponse(base64Response);
55
+ case "sui":
56
+ return parseSuiSignatureResponse(base64Response);
57
+ case "bip122":
58
+ case "bitcoin":
59
+ return parseBitcoinSignatureResponse(base64Response);
60
+ default:
61
+ return {
62
+ signature: base64Response,
63
+ rawSignature: base64Response
64
+ };
65
+ }
66
+ }
67
+ function parseTransactionResponse(base64RawTransaction, networkId, hash) {
68
+ if (hash) {
69
+ return {
70
+ hash,
71
+ rawTransaction: base64RawTransaction,
72
+ blockExplorer: (0, import_constants.getExplorerUrl)(networkId, "transaction", hash)
73
+ };
74
+ } else {
75
+ return {
76
+ rawTransaction: base64RawTransaction
77
+ };
78
+ }
79
+ }
80
+ function parseSolanaSignatureResponse(base64Response) {
81
+ try {
82
+ const signatureBytes = (0, import_base64url.base64urlDecode)(base64Response);
83
+ const signature = import_bs58.default.encode(signatureBytes);
84
+ return {
85
+ signature,
86
+ rawSignature: base64Response
87
+ };
88
+ } catch (error) {
89
+ return {
90
+ signature: base64Response,
91
+ rawSignature: base64Response
92
+ };
93
+ }
94
+ }
95
+ function parseEVMSignatureResponse(base64Response) {
96
+ try {
97
+ const signatureBytes = (0, import_base64url.base64urlDecode)(base64Response);
98
+ const signature = "0x" + import_buffer.Buffer.from(signatureBytes).toString("hex");
99
+ return {
100
+ signature,
101
+ rawSignature: base64Response
102
+ // Note: Most block explorers don't have direct signature lookup, only transaction lookup
103
+ };
104
+ } catch (error) {
105
+ const signature = base64Response.startsWith("0x") ? base64Response : "0x" + base64Response;
106
+ return {
107
+ signature,
108
+ rawSignature: base64Response
109
+ };
110
+ }
111
+ }
112
+ function parseSuiSignatureResponse(base64Response) {
113
+ try {
114
+ const signatureBytes = (0, import_base64url.base64urlDecode)(base64Response);
115
+ const signature = import_buffer.Buffer.from(signatureBytes).toString("base64");
116
+ return {
117
+ signature,
118
+ rawSignature: base64Response
119
+ };
120
+ } catch (error) {
121
+ return {
122
+ signature: base64Response,
123
+ rawSignature: base64Response
124
+ };
125
+ }
126
+ }
127
+ function parseBitcoinSignatureResponse(base64Response) {
128
+ try {
129
+ const signatureBytes = (0, import_base64url.base64urlDecode)(base64Response);
130
+ const signature = import_buffer.Buffer.from(signatureBytes).toString("hex");
131
+ return {
132
+ signature,
133
+ rawSignature: base64Response
134
+ };
135
+ } catch (error) {
136
+ return {
137
+ signature: base64Response,
138
+ rawSignature: base64Response
139
+ };
140
+ }
141
+ }
142
+
143
+ // src/index.ts
29
144
  function parseMessage(message) {
30
145
  return {
31
- base64url: (0, import_base64url.stringToBase64url)(message)
146
+ base64url: (0, import_base64url2.stringToBase64url)(message)
32
147
  };
33
148
  }
34
149
  async function parseTransaction(transaction, networkId) {
@@ -54,7 +169,7 @@ async function parseTransaction(transaction, networkId) {
54
169
  function parseSolanaTransaction(transaction) {
55
170
  if (transaction?.messageBytes != null) {
56
171
  return {
57
- base64url: (0, import_base64url.base64urlEncode)(transaction.messageBytes),
172
+ base64url: (0, import_base64url2.base64urlEncode)(transaction.messageBytes),
58
173
  originalFormat: "@solana/kit"
59
174
  };
60
175
  }
@@ -64,21 +179,21 @@ function parseSolanaTransaction(transaction) {
64
179
  verifySignatures: false
65
180
  });
66
181
  return {
67
- base64url: (0, import_base64url.base64urlEncode)(serialized),
182
+ base64url: (0, import_base64url2.base64urlEncode)(serialized),
68
183
  originalFormat: "@solana/web3.js"
69
184
  };
70
185
  }
71
186
  if (transaction instanceof Uint8Array) {
72
187
  return {
73
- base64url: (0, import_base64url.base64urlEncode)(transaction),
188
+ base64url: (0, import_base64url2.base64urlEncode)(transaction),
74
189
  originalFormat: "bytes"
75
190
  };
76
191
  }
77
192
  if (typeof transaction === "string") {
78
193
  try {
79
- const bytes = import_buffer.Buffer.from(transaction, "base64");
194
+ const bytes = import_buffer2.Buffer.from(transaction, "base64");
80
195
  return {
81
- base64url: (0, import_base64url.base64urlEncode)(new Uint8Array(bytes)),
196
+ base64url: (0, import_base64url2.base64urlEncode)(new Uint8Array(bytes)),
82
197
  originalFormat: "base64"
83
198
  };
84
199
  } catch {
@@ -93,28 +208,28 @@ function parseEVMTransaction(transaction) {
93
208
  JSON.stringify(transaction, (_key, value) => typeof value === "bigint" ? value.toString() : value)
94
209
  );
95
210
  return {
96
- base64url: (0, import_base64url.base64urlEncode)(bytes),
211
+ base64url: (0, import_base64url2.base64urlEncode)(bytes),
97
212
  originalFormat: "viem"
98
213
  };
99
214
  }
100
215
  if (transaction?.serialize && typeof transaction.serialize === "function") {
101
216
  const serialized = transaction.serialize();
102
- const bytes = new Uint8Array(import_buffer.Buffer.from(serialized.slice(2), "hex"));
217
+ const bytes = new Uint8Array(import_buffer2.Buffer.from(serialized.slice(2), "hex"));
103
218
  return {
104
- base64url: (0, import_base64url.base64urlEncode)(bytes),
219
+ base64url: (0, import_base64url2.base64urlEncode)(bytes),
105
220
  originalFormat: "ethers"
106
221
  };
107
222
  }
108
223
  if (transaction instanceof Uint8Array) {
109
224
  return {
110
- base64url: (0, import_base64url.base64urlEncode)(transaction),
225
+ base64url: (0, import_base64url2.base64urlEncode)(transaction),
111
226
  originalFormat: "bytes"
112
227
  };
113
228
  }
114
229
  if (typeof transaction === "string" && transaction.startsWith("0x")) {
115
- const bytes = new Uint8Array(import_buffer.Buffer.from(transaction.slice(2), "hex"));
230
+ const bytes = new Uint8Array(import_buffer2.Buffer.from(transaction.slice(2), "hex"));
116
231
  return {
117
- base64url: (0, import_base64url.base64urlEncode)(bytes),
232
+ base64url: (0, import_base64url2.base64urlEncode)(bytes),
118
233
  originalFormat: "hex"
119
234
  };
120
235
  }
@@ -124,13 +239,13 @@ async function parseSuiTransaction(transaction) {
124
239
  if (transaction?.serialize && typeof transaction.serialize === "function") {
125
240
  const serialized = transaction.serialize();
126
241
  return {
127
- base64url: (0, import_base64url.base64urlEncode)(serialized),
242
+ base64url: (0, import_base64url2.base64urlEncode)(serialized),
128
243
  originalFormat: "sui-sdk"
129
244
  };
130
245
  }
131
246
  if (transaction instanceof Uint8Array) {
132
247
  return {
133
- base64url: (0, import_base64url.base64urlEncode)(transaction),
248
+ base64url: (0, import_base64url2.base64urlEncode)(transaction),
134
249
  originalFormat: "bytes"
135
250
  };
136
251
  }
@@ -139,7 +254,7 @@ async function parseSuiTransaction(transaction) {
139
254
  if (built?.serialize && typeof built.serialize === "function") {
140
255
  const serialized = built.serialize();
141
256
  return {
142
- base64url: (0, import_base64url.base64urlEncode)(serialized),
257
+ base64url: (0, import_base64url2.base64urlEncode)(serialized),
143
258
  originalFormat: "transaction-block"
144
259
  };
145
260
  }
@@ -150,20 +265,20 @@ function parseBitcoinTransaction(transaction) {
150
265
  if (transaction?.toBuffer && typeof transaction.toBuffer === "function") {
151
266
  const buffer = transaction.toBuffer();
152
267
  return {
153
- base64url: (0, import_base64url.base64urlEncode)(new Uint8Array(buffer)),
268
+ base64url: (0, import_base64url2.base64urlEncode)(new Uint8Array(buffer)),
154
269
  originalFormat: "bitcoinjs-lib"
155
270
  };
156
271
  }
157
272
  if (transaction instanceof Uint8Array) {
158
273
  return {
159
- base64url: (0, import_base64url.base64urlEncode)(transaction),
274
+ base64url: (0, import_base64url2.base64urlEncode)(transaction),
160
275
  originalFormat: "bytes"
161
276
  };
162
277
  }
163
278
  if (typeof transaction === "string") {
164
- const bytes = new Uint8Array(import_buffer.Buffer.from(transaction, "hex"));
279
+ const bytes = new Uint8Array(import_buffer2.Buffer.from(transaction, "hex"));
165
280
  return {
166
- base64url: (0, import_base64url.base64urlEncode)(bytes),
281
+ base64url: (0, import_base64url2.base64urlEncode)(bytes),
167
282
  originalFormat: "hex"
168
283
  };
169
284
  }
@@ -172,5 +287,7 @@ function parseBitcoinTransaction(transaction) {
172
287
  // Annotate the CommonJS export names for ESM import in node:
173
288
  0 && (module.exports = {
174
289
  parseMessage,
175
- parseTransaction
290
+ parseSignMessageResponse,
291
+ parseTransaction,
292
+ parseTransactionResponse
176
293
  });
package/dist/index.mjs CHANGED
@@ -1,6 +1,109 @@
1
1
  // src/index.ts
2
2
  import { base64urlEncode, stringToBase64url } from "@phantom/base64url";
3
+ import { Buffer as Buffer2 } from "buffer";
4
+
5
+ // src/response-parsers.ts
6
+ import { getExplorerUrl } from "@phantom/constants";
7
+ import { base64urlDecode } from "@phantom/base64url";
3
8
  import { Buffer } from "buffer";
9
+ import bs58 from "bs58";
10
+ function parseSignMessageResponse(base64Response, networkId) {
11
+ const networkPrefix = networkId.split(":")[0].toLowerCase();
12
+ switch (networkPrefix) {
13
+ case "solana":
14
+ return parseSolanaSignatureResponse(base64Response);
15
+ case "eip155":
16
+ case "ethereum":
17
+ return parseEVMSignatureResponse(base64Response);
18
+ case "sui":
19
+ return parseSuiSignatureResponse(base64Response);
20
+ case "bip122":
21
+ case "bitcoin":
22
+ return parseBitcoinSignatureResponse(base64Response);
23
+ default:
24
+ return {
25
+ signature: base64Response,
26
+ rawSignature: base64Response
27
+ };
28
+ }
29
+ }
30
+ function parseTransactionResponse(base64RawTransaction, networkId, hash) {
31
+ if (hash) {
32
+ return {
33
+ hash,
34
+ rawTransaction: base64RawTransaction,
35
+ blockExplorer: getExplorerUrl(networkId, "transaction", hash)
36
+ };
37
+ } else {
38
+ return {
39
+ rawTransaction: base64RawTransaction
40
+ };
41
+ }
42
+ }
43
+ function parseSolanaSignatureResponse(base64Response) {
44
+ try {
45
+ const signatureBytes = base64urlDecode(base64Response);
46
+ const signature = bs58.encode(signatureBytes);
47
+ return {
48
+ signature,
49
+ rawSignature: base64Response
50
+ };
51
+ } catch (error) {
52
+ return {
53
+ signature: base64Response,
54
+ rawSignature: base64Response
55
+ };
56
+ }
57
+ }
58
+ function parseEVMSignatureResponse(base64Response) {
59
+ try {
60
+ const signatureBytes = base64urlDecode(base64Response);
61
+ const signature = "0x" + Buffer.from(signatureBytes).toString("hex");
62
+ return {
63
+ signature,
64
+ rawSignature: base64Response
65
+ // Note: Most block explorers don't have direct signature lookup, only transaction lookup
66
+ };
67
+ } catch (error) {
68
+ const signature = base64Response.startsWith("0x") ? base64Response : "0x" + base64Response;
69
+ return {
70
+ signature,
71
+ rawSignature: base64Response
72
+ };
73
+ }
74
+ }
75
+ function parseSuiSignatureResponse(base64Response) {
76
+ try {
77
+ const signatureBytes = base64urlDecode(base64Response);
78
+ const signature = Buffer.from(signatureBytes).toString("base64");
79
+ return {
80
+ signature,
81
+ rawSignature: base64Response
82
+ };
83
+ } catch (error) {
84
+ return {
85
+ signature: base64Response,
86
+ rawSignature: base64Response
87
+ };
88
+ }
89
+ }
90
+ function parseBitcoinSignatureResponse(base64Response) {
91
+ try {
92
+ const signatureBytes = base64urlDecode(base64Response);
93
+ const signature = Buffer.from(signatureBytes).toString("hex");
94
+ return {
95
+ signature,
96
+ rawSignature: base64Response
97
+ };
98
+ } catch (error) {
99
+ return {
100
+ signature: base64Response,
101
+ rawSignature: base64Response
102
+ };
103
+ }
104
+ }
105
+
106
+ // src/index.ts
4
107
  function parseMessage(message) {
5
108
  return {
6
109
  base64url: stringToBase64url(message)
@@ -51,7 +154,7 @@ function parseSolanaTransaction(transaction) {
51
154
  }
52
155
  if (typeof transaction === "string") {
53
156
  try {
54
- const bytes = Buffer.from(transaction, "base64");
157
+ const bytes = Buffer2.from(transaction, "base64");
55
158
  return {
56
159
  base64url: base64urlEncode(new Uint8Array(bytes)),
57
160
  originalFormat: "base64"
@@ -74,7 +177,7 @@ function parseEVMTransaction(transaction) {
74
177
  }
75
178
  if (transaction?.serialize && typeof transaction.serialize === "function") {
76
179
  const serialized = transaction.serialize();
77
- const bytes = new Uint8Array(Buffer.from(serialized.slice(2), "hex"));
180
+ const bytes = new Uint8Array(Buffer2.from(serialized.slice(2), "hex"));
78
181
  return {
79
182
  base64url: base64urlEncode(bytes),
80
183
  originalFormat: "ethers"
@@ -87,7 +190,7 @@ function parseEVMTransaction(transaction) {
87
190
  };
88
191
  }
89
192
  if (typeof transaction === "string" && transaction.startsWith("0x")) {
90
- const bytes = new Uint8Array(Buffer.from(transaction.slice(2), "hex"));
193
+ const bytes = new Uint8Array(Buffer2.from(transaction.slice(2), "hex"));
91
194
  return {
92
195
  base64url: base64urlEncode(bytes),
93
196
  originalFormat: "hex"
@@ -136,7 +239,7 @@ function parseBitcoinTransaction(transaction) {
136
239
  };
137
240
  }
138
241
  if (typeof transaction === "string") {
139
- const bytes = new Uint8Array(Buffer.from(transaction, "hex"));
242
+ const bytes = new Uint8Array(Buffer2.from(transaction, "hex"));
140
243
  return {
141
244
  base64url: base64urlEncode(bytes),
142
245
  originalFormat: "hex"
@@ -146,5 +249,7 @@ function parseBitcoinTransaction(transaction) {
146
249
  }
147
250
  export {
148
251
  parseMessage,
149
- parseTransaction
252
+ parseSignMessageResponse,
253
+ parseTransaction,
254
+ parseTransactionResponse
150
255
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phantom/parsers",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Transaction and message parsers for Phantom Wallet SDK",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -23,17 +23,29 @@
23
23
  "clean": "rm -rf dist",
24
24
  "test": "jest",
25
25
  "test:watch": "jest --watch",
26
+ "test:integration": "jest --testPathPattern=integration",
26
27
  "lint": "tsc --noEmit && eslint --cache . --ext .ts",
28
+ "check-types": "tsc --noEmit",
27
29
  "prettier": "prettier --write \"src/**/*.{ts}\""
28
30
  },
29
31
  "dependencies": {
30
32
  "@phantom/base64url": "^0.1.0",
31
- "@phantom/client": "^0.1.3",
33
+ "@phantom/constants": "^0.0.2",
34
+ "bs58": "^6.0.0",
32
35
  "buffer": "^6.0.3"
33
36
  },
37
+ "optionalDependencies": {
38
+ "@mysten/sui.js": "^0.50.0",
39
+ "@solana/kit": "^2.1.1",
40
+ "@solana/web3.js": "^1.95.0",
41
+ "bitcoinjs-lib": "^6.1.0",
42
+ "ethers": "^6.0.0",
43
+ "viem": "^2.0.0"
44
+ },
34
45
  "devDependencies": {
35
46
  "@types/jest": "^29.5.12",
36
47
  "@types/node": "^20.11.0",
48
+ "dotenv": "^16.4.5",
37
49
  "eslint": "8.53.0",
38
50
  "jest": "^29.7.0",
39
51
  "prettier": "^3.5.2",