@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 +18 -52
- package/dist/index.d.ts +10 -11
- package/dist/index.js +82 -61
- package/dist/index.mjs +81 -59
- 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,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
|
-
|
|
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
|
-
var import_constants = require("@phantom/constants");
|
|
47
46
|
var import_base64url = require("@phantom/base64url");
|
|
48
|
-
var
|
|
49
|
-
var
|
|
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
|
|
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,21 +107,12 @@ function parseSolanaSignatureResponse(base64Response) {
|
|
|
97
107
|
}
|
|
98
108
|
}
|
|
99
109
|
function parseEVMSignatureResponse(base64Response) {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
228
|
-
if (
|
|
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
|
-
|
|
234
|
-
originalFormat: "
|
|
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
|
|
231
|
+
const hex = serialized.startsWith("0x") ? serialized : "0x" + serialized;
|
|
240
232
|
return {
|
|
241
|
-
|
|
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
|
-
|
|
240
|
+
parsed: hex,
|
|
248
241
|
originalFormat: "bytes"
|
|
249
242
|
};
|
|
250
243
|
}
|
|
251
|
-
if (typeof transaction === "
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
325
|
-
|
|
345
|
+
parseToKmsTransaction,
|
|
346
|
+
parseTransactionResponse
|
|
326
347
|
});
|
package/dist/index.mjs
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
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
|
-
import { getExplorerUrl } from "@phantom/constants";
|
|
8
8
|
import { base64urlDecode } from "@phantom/base64url";
|
|
9
|
-
import {
|
|
10
|
-
import
|
|
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
|
|
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,21 +69,12 @@ function parseSolanaSignatureResponse(base64Response) {
|
|
|
58
69
|
}
|
|
59
70
|
}
|
|
60
71
|
function parseEVMSignatureResponse(base64Response) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
161
|
+
parsed: base64urlEncode(serialized),
|
|
166
162
|
originalFormat: "@solana/web3.js"
|
|
167
163
|
};
|
|
168
164
|
}
|
|
169
165
|
if (transaction instanceof Uint8Array) {
|
|
170
166
|
return {
|
|
171
|
-
|
|
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
|
-
|
|
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
|
|
189
|
-
if (
|
|
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
|
-
|
|
195
|
-
originalFormat: "
|
|
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
|
|
193
|
+
const hex = serialized.startsWith("0x") ? serialized : "0x" + serialized;
|
|
201
194
|
return {
|
|
202
|
-
|
|
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
|
-
|
|
202
|
+
parsed: hex,
|
|
209
203
|
originalFormat: "bytes"
|
|
210
204
|
};
|
|
211
205
|
}
|
|
212
|
-
if (typeof transaction === "
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
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
|
-
|
|
248
|
+
parsed: base64urlEncode(serialized),
|
|
226
249
|
originalFormat: "sui-sdk"
|
|
227
250
|
};
|
|
228
251
|
}
|
|
229
252
|
if (transaction instanceof Uint8Array) {
|
|
230
253
|
return {
|
|
231
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
285
|
-
|
|
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.
|
|
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": {
|