@phantom/parsers 1.0.0-beta.7 → 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 +18 -52
- package/dist/index.d.ts +10 -11
- package/dist/index.js +79 -63
- package/dist/index.mjs +78 -61
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @phantom/parsers
|
|
2
2
|
|
|
3
|
-
A utility package for parsing and converting
|
|
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
|
-
|
|
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
|
-
###
|
|
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
|
|
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 {
|
|
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
|
|
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
|
|
56
|
+
const result2 = await parseToKmsTransaction(rawBytes, NetworkId.SOLANA_MAINNET);
|
|
91
57
|
|
|
92
58
|
// Hex string
|
|
93
|
-
const result3 = await
|
|
59
|
+
const result3 = await parseToKmsTransaction("0x01020304", NetworkId.SOLANA_MAINNET);
|
|
94
60
|
```
|
|
95
61
|
|
|
96
62
|
### Ethereum/EVM
|
|
97
63
|
|
|
98
64
|
```typescript
|
|
99
|
-
import {
|
|
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
|
|
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
|
|
83
|
+
const result2 = await parseToKmsTransaction(rawTx, NetworkId.ETHEREUM_MAINNET);
|
|
118
84
|
|
|
119
85
|
// Hex-encoded transaction
|
|
120
|
-
const result3 = await
|
|
86
|
+
const result3 = await parseToKmsTransaction("0xf86c...", NetworkId.ETHEREUM_MAINNET);
|
|
121
87
|
```
|
|
122
88
|
|
|
123
89
|
### Bitcoin
|
|
124
90
|
|
|
125
91
|
```typescript
|
|
126
|
-
import {
|
|
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
|
|
99
|
+
const result = await parseToKmsTransaction(bitcoinTx, NetworkId.BITCOIN_MAINNET);
|
|
134
100
|
|
|
135
101
|
// Hex-encoded transaction
|
|
136
|
-
const result2 = await
|
|
102
|
+
const result2 = await parseToKmsTransaction("0x0100000001...", NetworkId.BITCOIN_MAINNET);
|
|
137
103
|
```
|
|
138
104
|
|
|
139
105
|
### Sui
|
|
140
106
|
|
|
141
107
|
```typescript
|
|
142
|
-
import {
|
|
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
|
|
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
|
|
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
|
|
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
|
|
44
|
-
|
|
45
|
-
|
|
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
|
|
48
|
+
declare function parseToKmsTransaction(transaction: any, networkId: NetworkId): Promise<ParsedTransaction>;
|
|
50
49
|
declare function parseSolanaKitTransactionToSolanaWeb3js(transaction: Transaction$1): any;
|
|
51
50
|
|
|
52
|
-
export {
|
|
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
|
-
|
|
38
|
-
|
|
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
|
|
85
|
+
rawTransaction,
|
|
76
86
|
blockExplorer: (0, import_constants.getExplorerUrl)(networkId, "transaction", hash)
|
|
77
87
|
};
|
|
78
88
|
} else {
|
|
79
89
|
return {
|
|
80
|
-
rawTransaction
|
|
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
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
233
|
-
if (
|
|
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
|
-
|
|
239
|
-
originalFormat: "
|
|
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
|
|
231
|
+
const hex = serialized.startsWith("0x") ? serialized : "0x" + serialized;
|
|
245
232
|
return {
|
|
246
|
-
|
|
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
|
-
|
|
240
|
+
parsed: hex,
|
|
253
241
|
originalFormat: "bytes"
|
|
254
242
|
};
|
|
255
243
|
}
|
|
256
|
-
if (typeof transaction === "
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
330
|
-
|
|
345
|
+
parseToKmsTransaction,
|
|
346
|
+
parseTransactionResponse
|
|
331
347
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { base64urlEncode
|
|
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
|
|
47
|
+
rawTransaction,
|
|
37
48
|
blockExplorer: getExplorerUrl(networkId, "transaction", hash)
|
|
38
49
|
};
|
|
39
50
|
} else {
|
|
40
51
|
return {
|
|
41
|
-
rawTransaction
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
161
|
+
parsed: base64urlEncode(serialized),
|
|
171
162
|
originalFormat: "@solana/web3.js"
|
|
172
163
|
};
|
|
173
164
|
}
|
|
174
165
|
if (transaction instanceof Uint8Array) {
|
|
175
166
|
return {
|
|
176
|
-
|
|
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
|
-
|
|
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
|
|
194
|
-
if (
|
|
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
|
-
|
|
200
|
-
originalFormat: "
|
|
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
|
|
193
|
+
const hex = serialized.startsWith("0x") ? serialized : "0x" + serialized;
|
|
206
194
|
return {
|
|
207
|
-
|
|
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
|
-
|
|
202
|
+
parsed: hex,
|
|
214
203
|
originalFormat: "bytes"
|
|
215
204
|
};
|
|
216
205
|
}
|
|
217
|
-
if (typeof transaction === "
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
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
|
-
|
|
248
|
+
parsed: base64urlEncode(serialized),
|
|
231
249
|
originalFormat: "sui-sdk"
|
|
232
250
|
};
|
|
233
251
|
}
|
|
234
252
|
if (transaction instanceof Uint8Array) {
|
|
235
253
|
return {
|
|
236
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
290
|
-
|
|
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.
|
|
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.
|
|
33
|
-
"@phantom/constants": "^1.0.0-beta.
|
|
34
|
-
"@phantom/sdk-types": "^1.0.0-beta.
|
|
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": {
|