@solana/connector 0.2.3 → 0.2.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/dist/{chunk-WPDCSFX2.mjs → chunk-26SWXQP6.mjs} +11 -8
- package/dist/chunk-26SWXQP6.mjs.map +1 -0
- package/dist/{chunk-NLPEO5GT.js → chunk-5MA4YO43.js} +3 -3
- package/dist/chunk-5MA4YO43.js.map +1 -0
- package/dist/{chunk-B6YBZB6H.js → chunk-6UTXGTYX.js} +26 -23
- package/dist/chunk-6UTXGTYX.js.map +1 -0
- package/dist/{chunk-X2X5TFXS.js → chunk-7DATF5NN.js} +4 -4
- package/dist/{chunk-X2X5TFXS.js.map → chunk-7DATF5NN.js.map} +1 -1
- package/dist/{chunk-E3DAIOYS.mjs → chunk-GM3PZ3WK.mjs} +11 -6
- package/dist/chunk-GM3PZ3WK.mjs.map +1 -0
- package/dist/{chunk-QST7XLMB.js → chunk-PNZYYZZS.js} +11 -6
- package/dist/chunk-PNZYYZZS.js.map +1 -0
- package/dist/{chunk-UOML5ULB.mjs → chunk-PP7GI6BR.mjs} +3 -3
- package/dist/{chunk-UOML5ULB.mjs.map → chunk-PP7GI6BR.mjs.map} +1 -1
- package/dist/{chunk-DFKGCW7K.mjs → chunk-STJOIQUF.mjs} +35 -8
- package/dist/chunk-STJOIQUF.mjs.map +1 -0
- package/dist/{chunk-ULEPN4NL.js → chunk-USIWRRHO.js} +34 -7
- package/dist/chunk-USIWRRHO.js.map +1 -0
- package/dist/{chunk-A7WQ3K75.mjs → chunk-ZBPAQUIP.mjs} +3 -3
- package/dist/chunk-ZBPAQUIP.mjs.map +1 -0
- package/dist/compat.d.mts +1 -1
- package/dist/compat.d.ts +1 -1
- package/dist/headless.d.mts +5 -6
- package/dist/headless.d.ts +5 -6
- package/dist/headless.js +113 -113
- package/dist/headless.mjs +3 -3
- package/dist/index.d.mts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.js +154 -154
- package/dist/index.mjs +4 -4
- package/dist/{protocol-G-z1lRqo.d.mts → protocol-nWSt9TTV.d.mts} +1 -1
- package/dist/{protocol-G-z1lRqo.d.ts → protocol-nWSt9TTV.d.ts} +1 -1
- package/dist/react.d.mts +23 -18
- package/dist/react.d.ts +23 -18
- package/dist/react.js +49 -49
- package/dist/react.mjs +2 -2
- package/dist/remote.d.mts +2 -2
- package/dist/remote.d.ts +2 -2
- package/dist/remote.js +13 -13
- package/dist/remote.mjs +2 -2
- package/dist/server.d.mts +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.js +13 -10
- package/dist/server.js.map +1 -1
- package/dist/server.mjs +5 -2
- package/dist/server.mjs.map +1 -1
- package/dist/{standard-shim-BB0Lkg_C.d.ts → standard-shim-BK2nn2ZT.d.ts} +15 -8
- package/dist/{standard-shim-n5phZB1d.d.mts → standard-shim-DSMKHCxD.d.mts} +15 -8
- package/dist/{transaction-signer-7NaYmP5w.d.ts → transaction-signer-B3eCsMfI.d.mts} +1 -1
- package/dist/{transaction-signer-7NaYmP5w.d.mts → transaction-signer-B3eCsMfI.d.ts} +1 -1
- package/dist/{walletconnect-F2M3PAAN.js → walletconnect-FFPQ6PDH.js} +8 -8
- package/dist/{walletconnect-F2M3PAAN.js.map → walletconnect-FFPQ6PDH.js.map} +1 -1
- package/dist/walletconnect-HMQQB3YM.mjs +3 -0
- package/dist/{walletconnect-Z6LPGALR.mjs.map → walletconnect-HMQQB3YM.mjs.map} +1 -1
- package/package.json +40 -31
- package/dist/chunk-A7WQ3K75.mjs.map +0 -1
- package/dist/chunk-B6YBZB6H.js.map +0 -1
- package/dist/chunk-DFKGCW7K.mjs.map +0 -1
- package/dist/chunk-E3DAIOYS.mjs.map +0 -1
- package/dist/chunk-NLPEO5GT.js.map +0 -1
- package/dist/chunk-QST7XLMB.js.map +0 -1
- package/dist/chunk-ULEPN4NL.js.map +0 -1
- package/dist/chunk-WPDCSFX2.mjs.map +0 -1
- package/dist/walletconnect-Z6LPGALR.mjs +0 -3
package/dist/remote.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkPNZYYZZS_js = require('./chunk-PNZYYZZS.js');
|
|
4
4
|
|
|
5
5
|
// src/remote/remote-wallet.ts
|
|
6
6
|
var DEFAULT_ICON = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAzMCAyOC4zMzE5IiBmaWxsPSJjdXJyZW50Q29sb3IiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGc+PHJlY3QgaGVpZ2h0PSIyNS4wODU1IiBvcGFjaXR5PSIwIiB3aWR0aD0iMjYuNTYyNSIgeD0iMCIgeT0iMCIvPjxwYXRoIGQ9Ik0xNy42NzgzIDE1LjEyNzdDMTcuNzc2MSAxNi41MzcgMTguNTE0NyAxNy43NzA5IDE5LjY1ODIgMTguNTI0MkwxOS42NTgyIDIxLjMxNjlDMTkuNjU1MSAyMS4zMTcxIDE5LjY1MTggMjEuMzE3MSAxOS42NDg0IDIxLjMxNzFMNi41NTI3MyAyMS4zMTcxQzUuNTA3ODEgMjEuMzE3MSA0Ljg4MjgxIDIwLjgyODkgNC44ODI4MSAyMC4wMTgzQzQuODgyODEgMTcuNDk4OCA4LjAzNzExIDE0LjAyMjIgMTMuMDk1NyAxNC4wMjIyQzE0Ljg4MDkgMTQuMDIyMiAxNi40Mjg2IDE0LjQ1MzUgMTcuNjc4MyAxNS4xMjc3Wk0xNy4wMTE3IDcuOTU3NzdDMTcuMDExNyAxMC4zOTkyIDE1LjE5NTMgMTIuMjc0MiAxMy4xMDU1IDEyLjI3NDJDMTEuMDA1OSAxMi4yNzQyIDkuMTk5MjIgMTAuMzk5MiA5LjE5OTIyIDcuOTc3M0M5LjE5OTIyIDUuNTg0NzIgMTEuMDE1NiAzLjc1ODU1IDEzLjEwNTUgMy43NTg1NUMxNS4xOTUzIDMuNzU4NTUgMTcuMDExNyA1LjU0NTY2IDE3LjAxMTcgNy45NTc3N1oiIGZpbGwtb3BhY2l0eT0iMC44NSIvPjxwYXRoIGQ9Ik0yMi4xMTkxIDExLjY5OEMyMC4zODA5IDExLjY5OCAxOS4wMDM5IDEzLjA5NDUgMTkuMDAzOSAxNC44MDM1QzE5LjAwMzkgMTYuMTMxNiAxOS43ODUyIDE3LjI1NDYgMjAuOTg2MyAxNy43MjM0TDIwLjk4NjMgMjIuNTU3NEMyMC45ODYzIDIyLjY3NDYgMjEuMDQ0OSAyMi43NjI1IDIxLjEyMyAyMi44NjAxTDIxLjk0MzQgMjMuNjgwNEMyMi4wNDEgMjMuNzc4MSAyMi4xNzc3IDIzLjc4NzggMjIuMjg1MiAyMy42ODA0TDIzLjgzNzkgMjIuMTM3NUMyMy45MzU1IDIyLjAzIDIzLjkzNTUgMjEuODkzMyAyMy44Mzc5IDIxLjc5NTdMMjIuODcxMSAyMC44Mjg5TDI0LjIwOSAxOS41MjAzQzI0LjMwNjYgMTkuNDMyNCAyNC4zMDY2IDE5LjI4NTkgMjQuMTg5NSAxOS4xNjg3TDIyLjg4MDkgMTcuODY5OUMyNC4zODQ4IDE3LjI1NDYgMjUuMjI0NiAxNi4xNjA5IDI1LjIyNDYgMTQuODAzNUMyNS4yMjQ2IDEzLjA5NDUgMjMuODM3OSAxMS42OTggMjIuMTE5MSAxMS42OThaTTIyLjEwOTQgMTMuMTUzMUMyMi42MzY3IDEzLjE1MzEgMjMuMDY2NCAxMy41ODI4IDIzLjA2NjQgMTQuMTEwMUMyMy4wNjY0IDE0LjY1NyAyMi42MzY3IDE1LjA4NjcgMjIuMTA5NCAxNS4wODY3QzIxLjU4MiAxNS4wODY3IDIxLjE0MjYgMTQuNjU3IDIxLjE0MjYgMTQuMTEwMUMyMS4xNDI2IDEzLjU4MjggMjEuNTcyMyAxMy4xNTMxIDIyLjEwOTQgMTMuMTUzMVoiIGZpbGwtb3BhY2l0eT0iMC44NSIvPjwvZz48L3N2Zz4=", DEFAULT_CHAINS = ["solana:mainnet", "solana:devnet"], RemoteWalletError = class extends Error {
|
|
@@ -26,8 +26,8 @@ function createRemoteSignerWallet(config) {
|
|
|
26
26
|
headers,
|
|
27
27
|
body: body ? JSON.stringify(body) : void 0
|
|
28
28
|
}), data = await response.json();
|
|
29
|
-
if (!response.ok ||
|
|
30
|
-
let errorData =
|
|
29
|
+
if (!response.ok || chunkPNZYYZZS_js.isErrorResponse(data)) {
|
|
30
|
+
let errorData = chunkPNZYYZZS_js.isErrorResponse(data) ? data.error : { code: "UNKNOWN", message: "Request failed", details: void 0 };
|
|
31
31
|
throw new RemoteWalletError(errorData.message, errorData.code, errorData.details);
|
|
32
32
|
}
|
|
33
33
|
return data;
|
|
@@ -91,10 +91,10 @@ function createRemoteSignerWallet(config) {
|
|
|
91
91
|
for (let input of inputs) {
|
|
92
92
|
let txBytes = input.transaction, req = {
|
|
93
93
|
operation: "signTransaction",
|
|
94
|
-
transaction:
|
|
94
|
+
transaction: chunkPNZYYZZS_js.encodeBase64(txBytes)
|
|
95
95
|
}, response = await request("POST", req);
|
|
96
96
|
results.push({
|
|
97
|
-
signedTransaction:
|
|
97
|
+
signedTransaction: chunkPNZYYZZS_js.decodeBase64(response.signedTransaction)
|
|
98
98
|
});
|
|
99
99
|
}
|
|
100
100
|
return results;
|
|
@@ -112,10 +112,10 @@ function createRemoteSignerWallet(config) {
|
|
|
112
112
|
allTxBytes.push(input.transaction);
|
|
113
113
|
let req = {
|
|
114
114
|
operation: "signAllTransactions",
|
|
115
|
-
transactions: allTxBytes.map((tx) =>
|
|
115
|
+
transactions: allTxBytes.map((tx) => chunkPNZYYZZS_js.encodeBase64(tx))
|
|
116
116
|
};
|
|
117
117
|
return (await request("POST", req)).signedTransactions.map((signedTx) => ({
|
|
118
|
-
signedTransaction:
|
|
118
|
+
signedTransaction: chunkPNZYYZZS_js.decodeBase64(signedTx)
|
|
119
119
|
}));
|
|
120
120
|
}
|
|
121
121
|
},
|
|
@@ -129,11 +129,11 @@ function createRemoteSignerWallet(config) {
|
|
|
129
129
|
for (let input of inputs) {
|
|
130
130
|
let req = {
|
|
131
131
|
operation: "signMessage",
|
|
132
|
-
message:
|
|
132
|
+
message: chunkPNZYYZZS_js.encodeBase64(input.message)
|
|
133
133
|
}, response = await request("POST", req);
|
|
134
134
|
results.push({
|
|
135
135
|
signedMessage: input.message,
|
|
136
|
-
signature:
|
|
136
|
+
signature: chunkPNZYYZZS_js.decodeBase64(response.signature)
|
|
137
137
|
});
|
|
138
138
|
}
|
|
139
139
|
return results;
|
|
@@ -155,7 +155,7 @@ function createRemoteSignerWallet(config) {
|
|
|
155
155
|
for (let input of inputs) {
|
|
156
156
|
let req = {
|
|
157
157
|
operation: "signAndSendTransaction",
|
|
158
|
-
transaction:
|
|
158
|
+
transaction: chunkPNZYYZZS_js.encodeBase64(input.transaction),
|
|
159
159
|
options: input.options
|
|
160
160
|
}, response = await request("POST", req), sigBytes = base58ToBytes(response.signature);
|
|
161
161
|
results.push({ signature: sigBytes });
|
|
@@ -196,15 +196,15 @@ function base58ToBytes(base58) {
|
|
|
196
196
|
|
|
197
197
|
Object.defineProperty(exports, "decodeBase64", {
|
|
198
198
|
enumerable: true,
|
|
199
|
-
get: function () { return
|
|
199
|
+
get: function () { return chunkPNZYYZZS_js.decodeBase64; }
|
|
200
200
|
});
|
|
201
201
|
Object.defineProperty(exports, "encodeBase64", {
|
|
202
202
|
enumerable: true,
|
|
203
|
-
get: function () { return
|
|
203
|
+
get: function () { return chunkPNZYYZZS_js.encodeBase64; }
|
|
204
204
|
});
|
|
205
205
|
Object.defineProperty(exports, "isErrorResponse", {
|
|
206
206
|
enumerable: true,
|
|
207
|
-
get: function () { return
|
|
207
|
+
get: function () { return chunkPNZYYZZS_js.isErrorResponse; }
|
|
208
208
|
});
|
|
209
209
|
exports.RemoteWalletError = RemoteWalletError;
|
|
210
210
|
exports.createRemoteSignerWallet = createRemoteSignerWallet;
|
package/dist/remote.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { encodeBase64, decodeBase64, isErrorResponse } from './chunk-
|
|
2
|
-
export { decodeBase64, encodeBase64, isErrorResponse } from './chunk-
|
|
1
|
+
import { encodeBase64, decodeBase64, isErrorResponse } from './chunk-GM3PZ3WK.mjs';
|
|
2
|
+
export { decodeBase64, encodeBase64, isErrorResponse } from './chunk-GM3PZ3WK.mjs';
|
|
3
3
|
|
|
4
4
|
// src/remote/remote-wallet.ts
|
|
5
5
|
var DEFAULT_ICON = "data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAzMCAyOC4zMzE5IiBmaWxsPSJjdXJyZW50Q29sb3IiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGc+PHJlY3QgaGVpZ2h0PSIyNS4wODU1IiBvcGFjaXR5PSIwIiB3aWR0aD0iMjYuNTYyNSIgeD0iMCIgeT0iMCIvPjxwYXRoIGQ9Ik0xNy42NzgzIDE1LjEyNzdDMTcuNzc2MSAxNi41MzcgMTguNTE0NyAxNy43NzA5IDE5LjY1ODIgMTguNTI0MkwxOS42NTgyIDIxLjMxNjlDMTkuNjU1MSAyMS4zMTcxIDE5LjY1MTggMjEuMzE3MSAxOS42NDg0IDIxLjMxNzFMNi41NTI3MyAyMS4zMTcxQzUuNTA3ODEgMjEuMzE3MSA0Ljg4MjgxIDIwLjgyODkgNC44ODI4MSAyMC4wMTgzQzQuODgyODEgMTcuNDk4OCA4LjAzNzExIDE0LjAyMjIgMTMuMDk1NyAxNC4wMjIyQzE0Ljg4MDkgMTQuMDIyMiAxNi40Mjg2IDE0LjQ1MzUgMTcuNjc4MyAxNS4xMjc3Wk0xNy4wMTE3IDcuOTU3NzdDMTcuMDExNyAxMC4zOTkyIDE1LjE5NTMgMTIuMjc0MiAxMy4xMDU1IDEyLjI3NDJDMTEuMDA1OSAxMi4yNzQyIDkuMTk5MjIgMTAuMzk5MiA5LjE5OTIyIDcuOTc3M0M5LjE5OTIyIDUuNTg0NzIgMTEuMDE1NiAzLjc1ODU1IDEzLjEwNTUgMy43NTg1NUMxNS4xOTUzIDMuNzU4NTUgMTcuMDExNyA1LjU0NTY2IDE3LjAxMTcgNy45NTc3N1oiIGZpbGwtb3BhY2l0eT0iMC44NSIvPjxwYXRoIGQ9Ik0yMi4xMTkxIDExLjY5OEMyMC4zODA5IDExLjY5OCAxOS4wMDM5IDEzLjA5NDUgMTkuMDAzOSAxNC44MDM1QzE5LjAwMzkgMTYuMTMxNiAxOS43ODUyIDE3LjI1NDYgMjAuOTg2MyAxNy43MjM0TDIwLjk4NjMgMjIuNTU3NEMyMC45ODYzIDIyLjY3NDYgMjEuMDQ0OSAyMi43NjI1IDIxLjEyMyAyMi44NjAxTDIxLjk0MzQgMjMuNjgwNEMyMi4wNDEgMjMuNzc4MSAyMi4xNzc3IDIzLjc4NzggMjIuMjg1MiAyMy42ODA0TDIzLjgzNzkgMjIuMTM3NUMyMy45MzU1IDIyLjAzIDIzLjkzNTUgMjEuODkzMyAyMy44Mzc5IDIxLjc5NTdMMjIuODcxMSAyMC44Mjg5TDI0LjIwOSAxOS41MjAzQzI0LjMwNjYgMTkuNDMyNCAyNC4zMDY2IDE5LjI4NTkgMjQuMTg5NSAxOS4xNjg3TDIyLjg4MDkgMTcuODY5OUMyNC4zODQ4IDE3LjI1NDYgMjUuMjI0NiAxNi4xNjA5IDI1LjIyNDYgMTQuODAzNUMyNS4yMjQ2IDEzLjA5NDUgMjMuODM3OSAxMS42OTggMjIuMTE5MSAxMS42OThaTTIyLjEwOTQgMTMuMTUzMUMyMi42MzY3IDEzLjE1MzEgMjMuMDY2NCAxMy41ODI4IDIzLjA2NjQgMTQuMTEwMUMyMy4wNjY0IDE0LjY1NyAyMi42MzY3IDE1LjA4NjcgMjIuMTA5NCAxNS4wODY3QzIxLjU4MiAxNS4wODY3IDIxLjE0MjYgMTQuNjU3IDIxLjE0MjYgMTQuMTEwMUMyMS4xNDI2IDEzLjU4MjggMjEuNTcyMyAxMy4xNTMxIDIyLjEwOTQgMTMuMTUzMVoiIGZpbGwtb3BhY2l0eT0iMC44NSIvPjwvZz48L3N2Zz4=", DEFAULT_CHAINS = ["solana:mainnet", "solana:devnet"], RemoteWalletError = class extends Error {
|
package/dist/server.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { a as RemoteSignerCapabilities, b as RemoteSignerErrorCode, c as RemoteSignerErrorResponse, d as RemoteSignerMetadata, e as RemoteSignerRequest } from './protocol-nWSt9TTV.mjs';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @solana/connector/server - Route Handlers
|
package/dist/server.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { a as RemoteSignerCapabilities, b as RemoteSignerErrorCode, c as RemoteSignerErrorResponse, d as RemoteSignerMetadata, e as RemoteSignerRequest } from './protocol-nWSt9TTV.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @solana/connector/server - Route Handlers
|
package/dist/server.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var chunkPNZYYZZS_js = require('./chunk-PNZYYZZS.js');
|
|
4
4
|
|
|
5
5
|
// src/server/route-handlers.ts
|
|
6
6
|
function jsonResponse(data, status = 200) {
|
|
@@ -14,8 +14,11 @@ function errorResponse(code, message, status = 400, details) {
|
|
|
14
14
|
error: { code, message, details }
|
|
15
15
|
}, status);
|
|
16
16
|
}
|
|
17
|
+
function getEnv(name) {
|
|
18
|
+
return globalThis.process?.env?.[name];
|
|
19
|
+
}
|
|
17
20
|
function defaultAuthorize(request) {
|
|
18
|
-
let token =
|
|
21
|
+
let token = getEnv("CONNECTOR_SIGNER_TOKEN");
|
|
19
22
|
if (!token)
|
|
20
23
|
return console.warn("[connector/server] CONNECTOR_SIGNER_TOKEN not set - rejecting all requests"), false;
|
|
21
24
|
let authHeader = request.headers.get("Authorization");
|
|
@@ -25,7 +28,7 @@ function defaultAuthorize(request) {
|
|
|
25
28
|
return (parts.length === 2 && parts[0].toLowerCase() === "bearer" ? parts[1] : authHeader) === token;
|
|
26
29
|
}
|
|
27
30
|
async function sendTransaction(rpc, signedTxBytes) {
|
|
28
|
-
let base64Tx =
|
|
31
|
+
let base64Tx = chunkPNZYYZZS_js.encodeBase64(signedTxBytes), result = await (await fetch(rpc.url, {
|
|
29
32
|
method: "POST",
|
|
30
33
|
headers: { "Content-Type": "application/json" },
|
|
31
34
|
body: JSON.stringify({
|
|
@@ -117,36 +120,36 @@ function createRemoteSignerRouteHandlers(config) {
|
|
|
117
120
|
case "signTransaction": {
|
|
118
121
|
if (!body.transaction)
|
|
119
122
|
return errorResponse("INVALID_REQUEST", "Missing transaction field", 400);
|
|
120
|
-
let txBytes =
|
|
123
|
+
let txBytes = chunkPNZYYZZS_js.decodeBase64(body.transaction);
|
|
121
124
|
if (policy?.validateTransaction && !await policy.validateTransaction(txBytes, request))
|
|
122
125
|
return errorResponse("POLICY_VIOLATION", "Transaction rejected by policy", 403);
|
|
123
126
|
let signedTx = await signer.signTransaction(txBytes), response = {
|
|
124
|
-
signedTransaction:
|
|
127
|
+
signedTransaction: chunkPNZYYZZS_js.encodeBase64(signedTx)
|
|
125
128
|
};
|
|
126
129
|
return jsonResponse(response);
|
|
127
130
|
}
|
|
128
131
|
case "signAllTransactions": {
|
|
129
132
|
if (!body.transactions || !Array.isArray(body.transactions))
|
|
130
133
|
return errorResponse("INVALID_REQUEST", "Missing transactions array", 400);
|
|
131
|
-
let txBytesArray = body.transactions.map((tx) =>
|
|
134
|
+
let txBytesArray = body.transactions.map((tx) => chunkPNZYYZZS_js.decodeBase64(tx));
|
|
132
135
|
if (policy?.validateTransaction) {
|
|
133
136
|
for (let txBytes of txBytesArray)
|
|
134
137
|
if (!await policy.validateTransaction(txBytes, request))
|
|
135
138
|
return errorResponse("POLICY_VIOLATION", "Transaction rejected by policy", 403);
|
|
136
139
|
}
|
|
137
140
|
let response = {
|
|
138
|
-
signedTransactions: (await signer.signAllTransactions(txBytesArray)).map((tx) =>
|
|
141
|
+
signedTransactions: (await signer.signAllTransactions(txBytesArray)).map((tx) => chunkPNZYYZZS_js.encodeBase64(tx))
|
|
139
142
|
};
|
|
140
143
|
return jsonResponse(response);
|
|
141
144
|
}
|
|
142
145
|
case "signMessage": {
|
|
143
146
|
if (!body.message)
|
|
144
147
|
return errorResponse("INVALID_REQUEST", "Missing message field", 400);
|
|
145
|
-
let messageBytes =
|
|
148
|
+
let messageBytes = chunkPNZYYZZS_js.decodeBase64(body.message);
|
|
146
149
|
if (policy?.validateMessage && !await policy.validateMessage(messageBytes, request))
|
|
147
150
|
return errorResponse("POLICY_VIOLATION", "Message rejected by policy", 403);
|
|
148
151
|
let signature = await signer.signMessage(messageBytes), response = {
|
|
149
|
-
signature:
|
|
152
|
+
signature: chunkPNZYYZZS_js.encodeBase64(signature)
|
|
150
153
|
};
|
|
151
154
|
return jsonResponse(response);
|
|
152
155
|
}
|
|
@@ -155,7 +158,7 @@ function createRemoteSignerRouteHandlers(config) {
|
|
|
155
158
|
return errorResponse("INVALID_OPERATION", "signAndSendTransaction not enabled", 400);
|
|
156
159
|
if (!body.transaction)
|
|
157
160
|
return errorResponse("INVALID_REQUEST", "Missing transaction field", 400);
|
|
158
|
-
let txBytes =
|
|
161
|
+
let txBytes = chunkPNZYYZZS_js.decodeBase64(body.transaction);
|
|
159
162
|
if (policy?.validateTransaction && !await policy.validateTransaction(txBytes, request))
|
|
160
163
|
return errorResponse("POLICY_VIOLATION", "Transaction rejected by policy", 403);
|
|
161
164
|
let signedTx = await signer.signTransaction(txBytes);
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/route-handlers.ts"],"names":["encodeBase64","decodeBase64"],"mappings":"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","file":"server.js","sourcesContent":["/**\n * @solana/connector/server - Route Handlers\n *\n * Creates Next.js Route Handler compatible GET/POST handlers for remote signing.\n * Designed for Node.js runtime (not Edge) to support crypto operations.\n */\n\nimport type {\n RemoteSignerMetadata,\n RemoteSignerCapabilities,\n RemoteSignerRequest,\n SignTransactionResponse,\n SignAllTransactionsResponse,\n SignMessageResponse,\n SignAndSendTransactionResponse,\n RemoteSignerErrorCode,\n RemoteSignerErrorResponse,\n} from '../remote/protocol';\nimport { decodeBase64, encodeBase64 } from '../remote/protocol';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Signer interface that providers must implement\n */\nexport interface RemoteSigner {\n /** Signer's Solana address (base58) */\n readonly address: string;\n\n /** Sign transaction bytes, return signed transaction bytes */\n signTransaction(transactionBytes: Uint8Array): Promise<Uint8Array>;\n\n /** Sign multiple transactions */\n signAllTransactions(transactions: Uint8Array[]): Promise<Uint8Array[]>;\n\n /** Sign a message, return 64-byte signature */\n signMessage(message: Uint8Array): Promise<Uint8Array>;\n\n /** Check if signer is available/healthy */\n isAvailable(): Promise<boolean>;\n}\n\n/**\n * Provider configuration\n */\nexport type ProviderType = 'fireblocks' | 'privy' | 'custom';\n\nexport interface FireblocksProviderConfig {\n type: 'fireblocks';\n /** Fireblocks API key */\n apiKey: string;\n /** RSA private key PEM for JWT signing */\n privateKeyPem: string;\n /** Vault account ID */\n vaultAccountId: string;\n /** Asset ID (default: 'SOL') */\n assetId?: string;\n /** API base URL (default: https://api.fireblocks.io) */\n apiBaseUrl?: string;\n}\n\nexport interface PrivyProviderConfig {\n type: 'privy';\n /** Privy app ID */\n appId: string;\n /** Privy app secret */\n appSecret: string;\n /** Privy wallet ID */\n walletId: string;\n /** API base URL (default: https://api.privy.io/v1) */\n apiBaseUrl?: string;\n}\n\nexport interface CustomProviderConfig {\n type: 'custom';\n /** Custom signer implementation */\n signer: RemoteSigner;\n}\n\nexport type ProviderConfig = FireblocksProviderConfig | PrivyProviderConfig | CustomProviderConfig;\n\n/**\n * Authorization callback\n */\nexport type AuthorizeCallback = (request: Request) => Promise<boolean> | boolean;\n\n/**\n * Policy validation callback\n */\nexport interface PolicyHooks {\n /** Validate a transaction before signing (return false to reject) */\n validateTransaction?: (transactionBytes: Uint8Array, request: Request) => Promise<boolean> | boolean;\n /** Validate a message before signing (return false to reject) */\n validateMessage?: (messageBytes: Uint8Array, request: Request) => Promise<boolean> | boolean;\n}\n\n/**\n * RPC configuration for sign+send operations\n */\nexport interface RpcConfig {\n /** Solana RPC endpoint URL */\n url: string;\n /** Commitment level for confirmations */\n commitment?: 'processed' | 'confirmed' | 'finalized';\n}\n\n/**\n * Route handler configuration\n */\nexport interface RemoteSignerRouteHandlersConfig {\n /** Provider configuration */\n provider: ProviderConfig;\n /**\n * Authorization callback. Default: checks for Authorization header matching CONNECTOR_SIGNER_TOKEN env var.\n * Return true to allow, false to reject.\n */\n authorize?: AuthorizeCallback;\n /** Policy hooks for transaction/message validation */\n policy?: PolicyHooks;\n /** RPC configuration (required for signAndSendTransaction) */\n rpc?: RpcConfig;\n /** Supported chains (default: ['solana:mainnet', 'solana:devnet']) */\n chains?: string[];\n /** Wallet name shown in metadata */\n name?: string;\n /** Wallet icon URL */\n icon?: string;\n}\n\n/**\n * Next.js compatible request/response types\n */\nexport interface NextRequest extends Request {\n // Next.js adds extra properties, but we only need standard Request\n}\n\nexport type NextResponse = Response;\n\n/**\n * Route handlers object returned by the factory\n */\nexport interface RouteHandlers {\n GET: (request: NextRequest) => Promise<NextResponse>;\n POST: (request: NextRequest) => Promise<NextResponse>;\n}\n\n// ============================================================================\n// Helper functions\n// ============================================================================\n\nfunction jsonResponse(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: { 'Content-Type': 'application/json' },\n });\n}\n\nfunction errorResponse(code: RemoteSignerErrorCode, message: string, status = 400, details?: unknown): Response {\n const body: RemoteSignerErrorResponse = {\n error: { code, message, details },\n };\n return jsonResponse(body, status);\n}\n\n/**\n * Default authorization: check Authorization header against CONNECTOR_SIGNER_TOKEN env var\n */\nfunction defaultAuthorize(request: Request): boolean {\n const token = process.env.CONNECTOR_SIGNER_TOKEN;\n if (!token) {\n // No token configured = reject all (safe default)\n console.warn('[connector/server] CONNECTOR_SIGNER_TOKEN not set - rejecting all requests');\n return false;\n }\n\n const authHeader = request.headers.get('Authorization');\n if (!authHeader) {\n return false;\n }\n\n // Support \"Bearer <token>\" format\n const parts = authHeader.split(' ');\n const providedToken = parts.length === 2 && parts[0].toLowerCase() === 'bearer' ? parts[1] : authHeader;\n\n return providedToken === token;\n}\n\n/**\n * Send a signed transaction to Solana RPC\n */\nasync function sendTransaction(rpc: RpcConfig, signedTxBytes: Uint8Array): Promise<string> {\n const base64Tx = encodeBase64(signedTxBytes);\n\n const response = await fetch(rpc.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'sendTransaction',\n params: [\n base64Tx,\n {\n encoding: 'base64',\n skipPreflight: false,\n preflightCommitment: rpc.commitment || 'confirmed',\n },\n ],\n }),\n });\n\n const result = await response.json();\n\n if (result.error) {\n throw new Error(result.error.message || 'RPC error');\n }\n\n return result.result as string;\n}\n\n// ============================================================================\n// Provider loader\n// ============================================================================\n\nlet cachedSigner: RemoteSigner | null = null;\n\nasync function loadSigner(config: ProviderConfig): Promise<RemoteSigner> {\n if (cachedSigner) {\n return cachedSigner;\n }\n\n if (config.type === 'custom') {\n cachedSigner = config.signer;\n return cachedSigner;\n }\n\n if (config.type === 'fireblocks') {\n const { loadFireblocksSigner } = await import('./providers/fireblocks');\n cachedSigner = await loadFireblocksSigner(config);\n return cachedSigner;\n }\n\n if (config.type === 'privy') {\n const { loadPrivySigner } = await import('./providers/privy');\n cachedSigner = await loadPrivySigner(config);\n return cachedSigner;\n }\n\n throw new Error(`Unknown provider type: ${(config as ProviderConfig).type}`);\n}\n\n// ============================================================================\n// Route Handler Factory\n// ============================================================================\n\n/**\n * Create Next.js Route Handlers for remote signing\n *\n * @example\n * ```typescript\n * // app/api/connector-signer/route.ts\n * import { createRemoteSignerRouteHandlers } from '@solana/connector/server';\n *\n * const { GET, POST } = createRemoteSignerRouteHandlers({\n * provider: {\n * type: 'fireblocks',\n * apiKey: process.env.FIREBLOCKS_API_KEY!,\n * privateKeyPem: process.env.FIREBLOCKS_PRIVATE_KEY!,\n * vaultAccountId: process.env.FIREBLOCKS_VAULT_ID!,\n * },\n * rpc: {\n * url: process.env.SOLANA_RPC_URL!,\n * },\n * });\n *\n * export { GET, POST };\n * export const runtime = 'nodejs';\n * ```\n */\nexport function createRemoteSignerRouteHandlers(config: RemoteSignerRouteHandlersConfig): RouteHandlers {\n const {\n provider,\n authorize = defaultAuthorize,\n policy,\n rpc,\n chains = ['solana:mainnet', 'solana:devnet'],\n name = 'Remote Signer',\n icon,\n } = config;\n\n // GET handler: return signer metadata\n async function GET(request: NextRequest): Promise<NextResponse> {\n try {\n // Check authorization\n const authorized = await authorize(request);\n if (!authorized) {\n return errorResponse('UNAUTHORIZED', 'Unauthorized', 401);\n }\n\n // Load signer\n const signer = await loadSigner(provider);\n\n // Check availability\n const available = await signer.isAvailable();\n if (!available) {\n return errorResponse('PROVIDER_ERROR', 'Signer not available', 503);\n }\n\n // Build capabilities\n const capabilities: RemoteSignerCapabilities = {\n signTransaction: true,\n signAllTransactions: true,\n signMessage: true,\n signAndSendTransaction: Boolean(rpc),\n };\n\n // Build metadata response\n const metadata: RemoteSignerMetadata = {\n address: signer.address,\n chains,\n capabilities,\n name,\n icon,\n };\n\n return jsonResponse(metadata);\n } catch (error) {\n console.error('[connector/server] GET error:', error);\n return errorResponse(\n 'INTERNAL_ERROR',\n error instanceof Error ? error.message : 'Internal server error',\n 500,\n );\n }\n }\n\n // POST handler: handle signing operations\n async function POST(request: NextRequest): Promise<NextResponse> {\n try {\n // Check authorization\n const authorized = await authorize(request);\n if (!authorized) {\n return errorResponse('UNAUTHORIZED', 'Unauthorized', 401);\n }\n\n // Parse request body\n let body: RemoteSignerRequest;\n try {\n body = await request.json();\n } catch {\n return errorResponse('INVALID_REQUEST', 'Invalid JSON body', 400);\n }\n\n if (!body.operation) {\n return errorResponse('INVALID_REQUEST', 'Missing operation field', 400);\n }\n\n // Load signer\n const signer = await loadSigner(provider);\n\n // Handle operations\n switch (body.operation) {\n case 'signTransaction': {\n if (!body.transaction) {\n return errorResponse('INVALID_REQUEST', 'Missing transaction field', 400);\n }\n\n const txBytes = decodeBase64(body.transaction);\n\n // Policy check\n if (policy?.validateTransaction) {\n const allowed = await policy.validateTransaction(txBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Transaction rejected by policy', 403);\n }\n }\n\n const signedTx = await signer.signTransaction(txBytes);\n const response: SignTransactionResponse = {\n signedTransaction: encodeBase64(signedTx),\n };\n return jsonResponse(response);\n }\n\n case 'signAllTransactions': {\n if (!body.transactions || !Array.isArray(body.transactions)) {\n return errorResponse('INVALID_REQUEST', 'Missing transactions array', 400);\n }\n\n const txBytesArray = body.transactions.map(tx => decodeBase64(tx));\n\n // Policy check for each transaction\n if (policy?.validateTransaction) {\n for (const txBytes of txBytesArray) {\n const allowed = await policy.validateTransaction(txBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Transaction rejected by policy', 403);\n }\n }\n }\n\n const signedTxs = await signer.signAllTransactions(txBytesArray);\n const response: SignAllTransactionsResponse = {\n signedTransactions: signedTxs.map(tx => encodeBase64(tx)),\n };\n return jsonResponse(response);\n }\n\n case 'signMessage': {\n if (!body.message) {\n return errorResponse('INVALID_REQUEST', 'Missing message field', 400);\n }\n\n const messageBytes = decodeBase64(body.message);\n\n // Policy check\n if (policy?.validateMessage) {\n const allowed = await policy.validateMessage(messageBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Message rejected by policy', 403);\n }\n }\n\n const signature = await signer.signMessage(messageBytes);\n const response: SignMessageResponse = {\n signature: encodeBase64(signature),\n };\n return jsonResponse(response);\n }\n\n case 'signAndSendTransaction': {\n if (!rpc) {\n return errorResponse('INVALID_OPERATION', 'signAndSendTransaction not enabled', 400);\n }\n\n if (!body.transaction) {\n return errorResponse('INVALID_REQUEST', 'Missing transaction field', 400);\n }\n\n const txBytes = decodeBase64(body.transaction);\n\n // Policy check\n if (policy?.validateTransaction) {\n const allowed = await policy.validateTransaction(txBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Transaction rejected by policy', 403);\n }\n }\n\n // Sign\n const signedTx = await signer.signTransaction(txBytes);\n\n // Send\n try {\n const signature = await sendTransaction(rpc, signedTx);\n const response: SignAndSendTransactionResponse = { signature };\n return jsonResponse(response);\n } catch (error) {\n return errorResponse(\n 'SEND_FAILED',\n error instanceof Error ? error.message : 'Failed to send transaction',\n 500,\n );\n }\n }\n\n default:\n return errorResponse(\n 'INVALID_OPERATION',\n `Unknown operation: ${(body as { operation: string }).operation}`,\n 400,\n );\n }\n } catch (error) {\n console.error('[connector/server] POST error:', error);\n\n // Check for known signer errors\n if (error instanceof Error) {\n if (error.message.includes('rate limit') || error.message.includes('429')) {\n return errorResponse('PROVIDER_ERROR', 'Rate limited, please retry', 429);\n }\n }\n\n return errorResponse('SIGNING_FAILED', error instanceof Error ? error.message : 'Signing failed', 500);\n }\n }\n\n return { GET, POST };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/server/route-handlers.ts"],"names":["encodeBase64","decodeBase64"],"mappings":"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","file":"server.js","sourcesContent":["/**\n * @solana/connector/server - Route Handlers\n *\n * Creates Next.js Route Handler compatible GET/POST handlers for remote signing.\n * Designed for Node.js runtime (not Edge) to support crypto operations.\n */\n\nimport type {\n RemoteSignerMetadata,\n RemoteSignerCapabilities,\n RemoteSignerRequest,\n SignTransactionResponse,\n SignAllTransactionsResponse,\n SignMessageResponse,\n SignAndSendTransactionResponse,\n RemoteSignerErrorCode,\n RemoteSignerErrorResponse,\n} from '../remote/protocol';\nimport { decodeBase64, encodeBase64 } from '../remote/protocol';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Signer interface that providers must implement\n */\nexport interface RemoteSigner {\n /** Signer's Solana address (base58) */\n readonly address: string;\n\n /** Sign transaction bytes, return signed transaction bytes */\n signTransaction(transactionBytes: Uint8Array): Promise<Uint8Array>;\n\n /** Sign multiple transactions */\n signAllTransactions(transactions: Uint8Array[]): Promise<Uint8Array[]>;\n\n /** Sign a message, return 64-byte signature */\n signMessage(message: Uint8Array): Promise<Uint8Array>;\n\n /** Check if signer is available/healthy */\n isAvailable(): Promise<boolean>;\n}\n\n/**\n * Provider configuration\n */\nexport type ProviderType = 'fireblocks' | 'privy' | 'custom';\n\nexport interface FireblocksProviderConfig {\n type: 'fireblocks';\n /** Fireblocks API key */\n apiKey: string;\n /** RSA private key PEM for JWT signing */\n privateKeyPem: string;\n /** Vault account ID */\n vaultAccountId: string;\n /** Asset ID (default: 'SOL') */\n assetId?: string;\n /** API base URL (default: https://api.fireblocks.io) */\n apiBaseUrl?: string;\n}\n\nexport interface PrivyProviderConfig {\n type: 'privy';\n /** Privy app ID */\n appId: string;\n /** Privy app secret */\n appSecret: string;\n /** Privy wallet ID */\n walletId: string;\n /** API base URL (default: https://api.privy.io/v1) */\n apiBaseUrl?: string;\n}\n\nexport interface CustomProviderConfig {\n type: 'custom';\n /** Custom signer implementation */\n signer: RemoteSigner;\n}\n\nexport type ProviderConfig = FireblocksProviderConfig | PrivyProviderConfig | CustomProviderConfig;\n\n/**\n * Authorization callback\n */\nexport type AuthorizeCallback = (request: Request) => Promise<boolean> | boolean;\n\n/**\n * Policy validation callback\n */\nexport interface PolicyHooks {\n /** Validate a transaction before signing (return false to reject) */\n validateTransaction?: (transactionBytes: Uint8Array, request: Request) => Promise<boolean> | boolean;\n /** Validate a message before signing (return false to reject) */\n validateMessage?: (messageBytes: Uint8Array, request: Request) => Promise<boolean> | boolean;\n}\n\n/**\n * RPC configuration for sign+send operations\n */\nexport interface RpcConfig {\n /** Solana RPC endpoint URL */\n url: string;\n /** Commitment level for confirmations */\n commitment?: 'processed' | 'confirmed' | 'finalized';\n}\n\n/**\n * Route handler configuration\n */\nexport interface RemoteSignerRouteHandlersConfig {\n /** Provider configuration */\n provider: ProviderConfig;\n /**\n * Authorization callback. Default: checks for Authorization header matching CONNECTOR_SIGNER_TOKEN env var.\n * Return true to allow, false to reject.\n */\n authorize?: AuthorizeCallback;\n /** Policy hooks for transaction/message validation */\n policy?: PolicyHooks;\n /** RPC configuration (required for signAndSendTransaction) */\n rpc?: RpcConfig;\n /** Supported chains (default: ['solana:mainnet', 'solana:devnet']) */\n chains?: string[];\n /** Wallet name shown in metadata */\n name?: string;\n /** Wallet icon URL */\n icon?: string;\n}\n\n/**\n * Next.js compatible request/response types\n */\nexport interface NextRequest extends Request {\n // Next.js adds extra properties, but we only need standard Request\n}\n\nexport type NextResponse = Response;\n\n/**\n * Route handlers object returned by the factory\n */\nexport interface RouteHandlers {\n GET: (request: NextRequest) => Promise<NextResponse>;\n POST: (request: NextRequest) => Promise<NextResponse>;\n}\n\n// ============================================================================\n// Helper functions\n// ============================================================================\n\nfunction jsonResponse(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: { 'Content-Type': 'application/json' },\n });\n}\n\nfunction errorResponse(code: RemoteSignerErrorCode, message: string, status = 400, details?: unknown): Response {\n const body: RemoteSignerErrorResponse = {\n error: { code, message, details },\n };\n return jsonResponse(body, status);\n}\n\nfunction getEnv(name: string): string | undefined {\n return (globalThis as { process?: { env?: Record<string, string | undefined> } }).process?.env?.[name];\n}\n\n/**\n * Default authorization: check Authorization header against CONNECTOR_SIGNER_TOKEN env var\n */\nfunction defaultAuthorize(request: Request): boolean {\n const token = getEnv('CONNECTOR_SIGNER_TOKEN');\n if (!token) {\n // No token configured = reject all (safe default)\n console.warn('[connector/server] CONNECTOR_SIGNER_TOKEN not set - rejecting all requests');\n return false;\n }\n\n const authHeader = request.headers.get('Authorization');\n if (!authHeader) {\n return false;\n }\n\n // Support \"Bearer <token>\" format\n const parts = authHeader.split(' ');\n const providedToken = parts.length === 2 && parts[0].toLowerCase() === 'bearer' ? parts[1] : authHeader;\n\n return providedToken === token;\n}\n\n/**\n * Send a signed transaction to Solana RPC\n */\nasync function sendTransaction(rpc: RpcConfig, signedTxBytes: Uint8Array): Promise<string> {\n const base64Tx = encodeBase64(signedTxBytes);\n\n const response = await fetch(rpc.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'sendTransaction',\n params: [\n base64Tx,\n {\n encoding: 'base64',\n skipPreflight: false,\n preflightCommitment: rpc.commitment || 'confirmed',\n },\n ],\n }),\n });\n\n const result = await response.json();\n\n if (result.error) {\n throw new Error(result.error.message || 'RPC error');\n }\n\n return result.result as string;\n}\n\n// ============================================================================\n// Provider loader\n// ============================================================================\n\nlet cachedSigner: RemoteSigner | null = null;\n\nasync function loadSigner(config: ProviderConfig): Promise<RemoteSigner> {\n if (cachedSigner) {\n return cachedSigner;\n }\n\n if (config.type === 'custom') {\n cachedSigner = config.signer;\n return cachedSigner;\n }\n\n if (config.type === 'fireblocks') {\n const { loadFireblocksSigner } = await import('./providers/fireblocks');\n cachedSigner = await loadFireblocksSigner(config);\n return cachedSigner;\n }\n\n if (config.type === 'privy') {\n const { loadPrivySigner } = await import('./providers/privy');\n cachedSigner = await loadPrivySigner(config);\n return cachedSigner;\n }\n\n throw new Error(`Unknown provider type: ${(config as ProviderConfig).type}`);\n}\n\n// ============================================================================\n// Route Handler Factory\n// ============================================================================\n\n/**\n * Create Next.js Route Handlers for remote signing\n *\n * @example\n * ```typescript\n * // app/api/connector-signer/route.ts\n * import { createRemoteSignerRouteHandlers } from '@solana/connector/server';\n *\n * const { GET, POST } = createRemoteSignerRouteHandlers({\n * provider: {\n * type: 'fireblocks',\n * apiKey: process.env.FIREBLOCKS_API_KEY!,\n * privateKeyPem: process.env.FIREBLOCKS_PRIVATE_KEY!,\n * vaultAccountId: process.env.FIREBLOCKS_VAULT_ID!,\n * },\n * rpc: {\n * url: process.env.SOLANA_RPC_URL!,\n * },\n * });\n *\n * export { GET, POST };\n * export const runtime = 'nodejs';\n * ```\n */\nexport function createRemoteSignerRouteHandlers(config: RemoteSignerRouteHandlersConfig): RouteHandlers {\n const {\n provider,\n authorize = defaultAuthorize,\n policy,\n rpc,\n chains = ['solana:mainnet', 'solana:devnet'],\n name = 'Remote Signer',\n icon,\n } = config;\n\n // GET handler: return signer metadata\n async function GET(request: NextRequest): Promise<NextResponse> {\n try {\n // Check authorization\n const authorized = await authorize(request);\n if (!authorized) {\n return errorResponse('UNAUTHORIZED', 'Unauthorized', 401);\n }\n\n // Load signer\n const signer = await loadSigner(provider);\n\n // Check availability\n const available = await signer.isAvailable();\n if (!available) {\n return errorResponse('PROVIDER_ERROR', 'Signer not available', 503);\n }\n\n // Build capabilities\n const capabilities: RemoteSignerCapabilities = {\n signTransaction: true,\n signAllTransactions: true,\n signMessage: true,\n signAndSendTransaction: Boolean(rpc),\n };\n\n // Build metadata response\n const metadata: RemoteSignerMetadata = {\n address: signer.address,\n chains,\n capabilities,\n name,\n icon,\n };\n\n return jsonResponse(metadata);\n } catch (error) {\n console.error('[connector/server] GET error:', error);\n return errorResponse(\n 'INTERNAL_ERROR',\n error instanceof Error ? error.message : 'Internal server error',\n 500,\n );\n }\n }\n\n // POST handler: handle signing operations\n async function POST(request: NextRequest): Promise<NextResponse> {\n try {\n // Check authorization\n const authorized = await authorize(request);\n if (!authorized) {\n return errorResponse('UNAUTHORIZED', 'Unauthorized', 401);\n }\n\n // Parse request body\n let body: RemoteSignerRequest;\n try {\n body = await request.json();\n } catch {\n return errorResponse('INVALID_REQUEST', 'Invalid JSON body', 400);\n }\n\n if (!body.operation) {\n return errorResponse('INVALID_REQUEST', 'Missing operation field', 400);\n }\n\n // Load signer\n const signer = await loadSigner(provider);\n\n // Handle operations\n switch (body.operation) {\n case 'signTransaction': {\n if (!body.transaction) {\n return errorResponse('INVALID_REQUEST', 'Missing transaction field', 400);\n }\n\n const txBytes = decodeBase64(body.transaction);\n\n // Policy check\n if (policy?.validateTransaction) {\n const allowed = await policy.validateTransaction(txBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Transaction rejected by policy', 403);\n }\n }\n\n const signedTx = await signer.signTransaction(txBytes);\n const response: SignTransactionResponse = {\n signedTransaction: encodeBase64(signedTx),\n };\n return jsonResponse(response);\n }\n\n case 'signAllTransactions': {\n if (!body.transactions || !Array.isArray(body.transactions)) {\n return errorResponse('INVALID_REQUEST', 'Missing transactions array', 400);\n }\n\n const txBytesArray = body.transactions.map(tx => decodeBase64(tx));\n\n // Policy check for each transaction\n if (policy?.validateTransaction) {\n for (const txBytes of txBytesArray) {\n const allowed = await policy.validateTransaction(txBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Transaction rejected by policy', 403);\n }\n }\n }\n\n const signedTxs = await signer.signAllTransactions(txBytesArray);\n const response: SignAllTransactionsResponse = {\n signedTransactions: signedTxs.map(tx => encodeBase64(tx)),\n };\n return jsonResponse(response);\n }\n\n case 'signMessage': {\n if (!body.message) {\n return errorResponse('INVALID_REQUEST', 'Missing message field', 400);\n }\n\n const messageBytes = decodeBase64(body.message);\n\n // Policy check\n if (policy?.validateMessage) {\n const allowed = await policy.validateMessage(messageBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Message rejected by policy', 403);\n }\n }\n\n const signature = await signer.signMessage(messageBytes);\n const response: SignMessageResponse = {\n signature: encodeBase64(signature),\n };\n return jsonResponse(response);\n }\n\n case 'signAndSendTransaction': {\n if (!rpc) {\n return errorResponse('INVALID_OPERATION', 'signAndSendTransaction not enabled', 400);\n }\n\n if (!body.transaction) {\n return errorResponse('INVALID_REQUEST', 'Missing transaction field', 400);\n }\n\n const txBytes = decodeBase64(body.transaction);\n\n // Policy check\n if (policy?.validateTransaction) {\n const allowed = await policy.validateTransaction(txBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Transaction rejected by policy', 403);\n }\n }\n\n // Sign\n const signedTx = await signer.signTransaction(txBytes);\n\n // Send\n try {\n const signature = await sendTransaction(rpc, signedTx);\n const response: SignAndSendTransactionResponse = { signature };\n return jsonResponse(response);\n } catch (error) {\n return errorResponse(\n 'SEND_FAILED',\n error instanceof Error ? error.message : 'Failed to send transaction',\n 500,\n );\n }\n }\n\n default:\n return errorResponse(\n 'INVALID_OPERATION',\n `Unknown operation: ${(body as { operation: string }).operation}`,\n 400,\n );\n }\n } catch (error) {\n console.error('[connector/server] POST error:', error);\n\n // Check for known signer errors\n if (error instanceof Error) {\n if (error.message.includes('rate limit') || error.message.includes('429')) {\n return errorResponse('PROVIDER_ERROR', 'Rate limited, please retry', 429);\n }\n }\n\n return errorResponse('SIGNING_FAILED', error instanceof Error ? error.message : 'Signing failed', 500);\n }\n }\n\n return { GET, POST };\n}\n"]}
|
package/dist/server.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { decodeBase64, encodeBase64 } from './chunk-
|
|
1
|
+
import { decodeBase64, encodeBase64 } from './chunk-GM3PZ3WK.mjs';
|
|
2
2
|
|
|
3
3
|
// src/server/route-handlers.ts
|
|
4
4
|
function jsonResponse(data, status = 200) {
|
|
@@ -12,8 +12,11 @@ function errorResponse(code, message, status = 400, details) {
|
|
|
12
12
|
error: { code, message, details }
|
|
13
13
|
}, status);
|
|
14
14
|
}
|
|
15
|
+
function getEnv(name) {
|
|
16
|
+
return globalThis.process?.env?.[name];
|
|
17
|
+
}
|
|
15
18
|
function defaultAuthorize(request) {
|
|
16
|
-
let token =
|
|
19
|
+
let token = getEnv("CONNECTOR_SIGNER_TOKEN");
|
|
17
20
|
if (!token)
|
|
18
21
|
return console.warn("[connector/server] CONNECTOR_SIGNER_TOKEN not set - rejecting all requests"), false;
|
|
19
22
|
let authHeader = request.headers.get("Authorization");
|
package/dist/server.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/route-handlers.ts"],"names":[],"mappings":"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","file":"server.mjs","sourcesContent":["/**\n * @solana/connector/server - Route Handlers\n *\n * Creates Next.js Route Handler compatible GET/POST handlers for remote signing.\n * Designed for Node.js runtime (not Edge) to support crypto operations.\n */\n\nimport type {\n RemoteSignerMetadata,\n RemoteSignerCapabilities,\n RemoteSignerRequest,\n SignTransactionResponse,\n SignAllTransactionsResponse,\n SignMessageResponse,\n SignAndSendTransactionResponse,\n RemoteSignerErrorCode,\n RemoteSignerErrorResponse,\n} from '../remote/protocol';\nimport { decodeBase64, encodeBase64 } from '../remote/protocol';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Signer interface that providers must implement\n */\nexport interface RemoteSigner {\n /** Signer's Solana address (base58) */\n readonly address: string;\n\n /** Sign transaction bytes, return signed transaction bytes */\n signTransaction(transactionBytes: Uint8Array): Promise<Uint8Array>;\n\n /** Sign multiple transactions */\n signAllTransactions(transactions: Uint8Array[]): Promise<Uint8Array[]>;\n\n /** Sign a message, return 64-byte signature */\n signMessage(message: Uint8Array): Promise<Uint8Array>;\n\n /** Check if signer is available/healthy */\n isAvailable(): Promise<boolean>;\n}\n\n/**\n * Provider configuration\n */\nexport type ProviderType = 'fireblocks' | 'privy' | 'custom';\n\nexport interface FireblocksProviderConfig {\n type: 'fireblocks';\n /** Fireblocks API key */\n apiKey: string;\n /** RSA private key PEM for JWT signing */\n privateKeyPem: string;\n /** Vault account ID */\n vaultAccountId: string;\n /** Asset ID (default: 'SOL') */\n assetId?: string;\n /** API base URL (default: https://api.fireblocks.io) */\n apiBaseUrl?: string;\n}\n\nexport interface PrivyProviderConfig {\n type: 'privy';\n /** Privy app ID */\n appId: string;\n /** Privy app secret */\n appSecret: string;\n /** Privy wallet ID */\n walletId: string;\n /** API base URL (default: https://api.privy.io/v1) */\n apiBaseUrl?: string;\n}\n\nexport interface CustomProviderConfig {\n type: 'custom';\n /** Custom signer implementation */\n signer: RemoteSigner;\n}\n\nexport type ProviderConfig = FireblocksProviderConfig | PrivyProviderConfig | CustomProviderConfig;\n\n/**\n * Authorization callback\n */\nexport type AuthorizeCallback = (request: Request) => Promise<boolean> | boolean;\n\n/**\n * Policy validation callback\n */\nexport interface PolicyHooks {\n /** Validate a transaction before signing (return false to reject) */\n validateTransaction?: (transactionBytes: Uint8Array, request: Request) => Promise<boolean> | boolean;\n /** Validate a message before signing (return false to reject) */\n validateMessage?: (messageBytes: Uint8Array, request: Request) => Promise<boolean> | boolean;\n}\n\n/**\n * RPC configuration for sign+send operations\n */\nexport interface RpcConfig {\n /** Solana RPC endpoint URL */\n url: string;\n /** Commitment level for confirmations */\n commitment?: 'processed' | 'confirmed' | 'finalized';\n}\n\n/**\n * Route handler configuration\n */\nexport interface RemoteSignerRouteHandlersConfig {\n /** Provider configuration */\n provider: ProviderConfig;\n /**\n * Authorization callback. Default: checks for Authorization header matching CONNECTOR_SIGNER_TOKEN env var.\n * Return true to allow, false to reject.\n */\n authorize?: AuthorizeCallback;\n /** Policy hooks for transaction/message validation */\n policy?: PolicyHooks;\n /** RPC configuration (required for signAndSendTransaction) */\n rpc?: RpcConfig;\n /** Supported chains (default: ['solana:mainnet', 'solana:devnet']) */\n chains?: string[];\n /** Wallet name shown in metadata */\n name?: string;\n /** Wallet icon URL */\n icon?: string;\n}\n\n/**\n * Next.js compatible request/response types\n */\nexport interface NextRequest extends Request {\n // Next.js adds extra properties, but we only need standard Request\n}\n\nexport type NextResponse = Response;\n\n/**\n * Route handlers object returned by the factory\n */\nexport interface RouteHandlers {\n GET: (request: NextRequest) => Promise<NextResponse>;\n POST: (request: NextRequest) => Promise<NextResponse>;\n}\n\n// ============================================================================\n// Helper functions\n// ============================================================================\n\nfunction jsonResponse(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: { 'Content-Type': 'application/json' },\n });\n}\n\nfunction errorResponse(code: RemoteSignerErrorCode, message: string, status = 400, details?: unknown): Response {\n const body: RemoteSignerErrorResponse = {\n error: { code, message, details },\n };\n return jsonResponse(body, status);\n}\n\n/**\n * Default authorization: check Authorization header against CONNECTOR_SIGNER_TOKEN env var\n */\nfunction defaultAuthorize(request: Request): boolean {\n const token = process.env.CONNECTOR_SIGNER_TOKEN;\n if (!token) {\n // No token configured = reject all (safe default)\n console.warn('[connector/server] CONNECTOR_SIGNER_TOKEN not set - rejecting all requests');\n return false;\n }\n\n const authHeader = request.headers.get('Authorization');\n if (!authHeader) {\n return false;\n }\n\n // Support \"Bearer <token>\" format\n const parts = authHeader.split(' ');\n const providedToken = parts.length === 2 && parts[0].toLowerCase() === 'bearer' ? parts[1] : authHeader;\n\n return providedToken === token;\n}\n\n/**\n * Send a signed transaction to Solana RPC\n */\nasync function sendTransaction(rpc: RpcConfig, signedTxBytes: Uint8Array): Promise<string> {\n const base64Tx = encodeBase64(signedTxBytes);\n\n const response = await fetch(rpc.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'sendTransaction',\n params: [\n base64Tx,\n {\n encoding: 'base64',\n skipPreflight: false,\n preflightCommitment: rpc.commitment || 'confirmed',\n },\n ],\n }),\n });\n\n const result = await response.json();\n\n if (result.error) {\n throw new Error(result.error.message || 'RPC error');\n }\n\n return result.result as string;\n}\n\n// ============================================================================\n// Provider loader\n// ============================================================================\n\nlet cachedSigner: RemoteSigner | null = null;\n\nasync function loadSigner(config: ProviderConfig): Promise<RemoteSigner> {\n if (cachedSigner) {\n return cachedSigner;\n }\n\n if (config.type === 'custom') {\n cachedSigner = config.signer;\n return cachedSigner;\n }\n\n if (config.type === 'fireblocks') {\n const { loadFireblocksSigner } = await import('./providers/fireblocks');\n cachedSigner = await loadFireblocksSigner(config);\n return cachedSigner;\n }\n\n if (config.type === 'privy') {\n const { loadPrivySigner } = await import('./providers/privy');\n cachedSigner = await loadPrivySigner(config);\n return cachedSigner;\n }\n\n throw new Error(`Unknown provider type: ${(config as ProviderConfig).type}`);\n}\n\n// ============================================================================\n// Route Handler Factory\n// ============================================================================\n\n/**\n * Create Next.js Route Handlers for remote signing\n *\n * @example\n * ```typescript\n * // app/api/connector-signer/route.ts\n * import { createRemoteSignerRouteHandlers } from '@solana/connector/server';\n *\n * const { GET, POST } = createRemoteSignerRouteHandlers({\n * provider: {\n * type: 'fireblocks',\n * apiKey: process.env.FIREBLOCKS_API_KEY!,\n * privateKeyPem: process.env.FIREBLOCKS_PRIVATE_KEY!,\n * vaultAccountId: process.env.FIREBLOCKS_VAULT_ID!,\n * },\n * rpc: {\n * url: process.env.SOLANA_RPC_URL!,\n * },\n * });\n *\n * export { GET, POST };\n * export const runtime = 'nodejs';\n * ```\n */\nexport function createRemoteSignerRouteHandlers(config: RemoteSignerRouteHandlersConfig): RouteHandlers {\n const {\n provider,\n authorize = defaultAuthorize,\n policy,\n rpc,\n chains = ['solana:mainnet', 'solana:devnet'],\n name = 'Remote Signer',\n icon,\n } = config;\n\n // GET handler: return signer metadata\n async function GET(request: NextRequest): Promise<NextResponse> {\n try {\n // Check authorization\n const authorized = await authorize(request);\n if (!authorized) {\n return errorResponse('UNAUTHORIZED', 'Unauthorized', 401);\n }\n\n // Load signer\n const signer = await loadSigner(provider);\n\n // Check availability\n const available = await signer.isAvailable();\n if (!available) {\n return errorResponse('PROVIDER_ERROR', 'Signer not available', 503);\n }\n\n // Build capabilities\n const capabilities: RemoteSignerCapabilities = {\n signTransaction: true,\n signAllTransactions: true,\n signMessage: true,\n signAndSendTransaction: Boolean(rpc),\n };\n\n // Build metadata response\n const metadata: RemoteSignerMetadata = {\n address: signer.address,\n chains,\n capabilities,\n name,\n icon,\n };\n\n return jsonResponse(metadata);\n } catch (error) {\n console.error('[connector/server] GET error:', error);\n return errorResponse(\n 'INTERNAL_ERROR',\n error instanceof Error ? error.message : 'Internal server error',\n 500,\n );\n }\n }\n\n // POST handler: handle signing operations\n async function POST(request: NextRequest): Promise<NextResponse> {\n try {\n // Check authorization\n const authorized = await authorize(request);\n if (!authorized) {\n return errorResponse('UNAUTHORIZED', 'Unauthorized', 401);\n }\n\n // Parse request body\n let body: RemoteSignerRequest;\n try {\n body = await request.json();\n } catch {\n return errorResponse('INVALID_REQUEST', 'Invalid JSON body', 400);\n }\n\n if (!body.operation) {\n return errorResponse('INVALID_REQUEST', 'Missing operation field', 400);\n }\n\n // Load signer\n const signer = await loadSigner(provider);\n\n // Handle operations\n switch (body.operation) {\n case 'signTransaction': {\n if (!body.transaction) {\n return errorResponse('INVALID_REQUEST', 'Missing transaction field', 400);\n }\n\n const txBytes = decodeBase64(body.transaction);\n\n // Policy check\n if (policy?.validateTransaction) {\n const allowed = await policy.validateTransaction(txBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Transaction rejected by policy', 403);\n }\n }\n\n const signedTx = await signer.signTransaction(txBytes);\n const response: SignTransactionResponse = {\n signedTransaction: encodeBase64(signedTx),\n };\n return jsonResponse(response);\n }\n\n case 'signAllTransactions': {\n if (!body.transactions || !Array.isArray(body.transactions)) {\n return errorResponse('INVALID_REQUEST', 'Missing transactions array', 400);\n }\n\n const txBytesArray = body.transactions.map(tx => decodeBase64(tx));\n\n // Policy check for each transaction\n if (policy?.validateTransaction) {\n for (const txBytes of txBytesArray) {\n const allowed = await policy.validateTransaction(txBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Transaction rejected by policy', 403);\n }\n }\n }\n\n const signedTxs = await signer.signAllTransactions(txBytesArray);\n const response: SignAllTransactionsResponse = {\n signedTransactions: signedTxs.map(tx => encodeBase64(tx)),\n };\n return jsonResponse(response);\n }\n\n case 'signMessage': {\n if (!body.message) {\n return errorResponse('INVALID_REQUEST', 'Missing message field', 400);\n }\n\n const messageBytes = decodeBase64(body.message);\n\n // Policy check\n if (policy?.validateMessage) {\n const allowed = await policy.validateMessage(messageBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Message rejected by policy', 403);\n }\n }\n\n const signature = await signer.signMessage(messageBytes);\n const response: SignMessageResponse = {\n signature: encodeBase64(signature),\n };\n return jsonResponse(response);\n }\n\n case 'signAndSendTransaction': {\n if (!rpc) {\n return errorResponse('INVALID_OPERATION', 'signAndSendTransaction not enabled', 400);\n }\n\n if (!body.transaction) {\n return errorResponse('INVALID_REQUEST', 'Missing transaction field', 400);\n }\n\n const txBytes = decodeBase64(body.transaction);\n\n // Policy check\n if (policy?.validateTransaction) {\n const allowed = await policy.validateTransaction(txBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Transaction rejected by policy', 403);\n }\n }\n\n // Sign\n const signedTx = await signer.signTransaction(txBytes);\n\n // Send\n try {\n const signature = await sendTransaction(rpc, signedTx);\n const response: SignAndSendTransactionResponse = { signature };\n return jsonResponse(response);\n } catch (error) {\n return errorResponse(\n 'SEND_FAILED',\n error instanceof Error ? error.message : 'Failed to send transaction',\n 500,\n );\n }\n }\n\n default:\n return errorResponse(\n 'INVALID_OPERATION',\n `Unknown operation: ${(body as { operation: string }).operation}`,\n 400,\n );\n }\n } catch (error) {\n console.error('[connector/server] POST error:', error);\n\n // Check for known signer errors\n if (error instanceof Error) {\n if (error.message.includes('rate limit') || error.message.includes('429')) {\n return errorResponse('PROVIDER_ERROR', 'Rate limited, please retry', 429);\n }\n }\n\n return errorResponse('SIGNING_FAILED', error instanceof Error ? error.message : 'Signing failed', 500);\n }\n }\n\n return { GET, POST };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/server/route-handlers.ts"],"names":[],"mappings":"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","file":"server.mjs","sourcesContent":["/**\n * @solana/connector/server - Route Handlers\n *\n * Creates Next.js Route Handler compatible GET/POST handlers for remote signing.\n * Designed for Node.js runtime (not Edge) to support crypto operations.\n */\n\nimport type {\n RemoteSignerMetadata,\n RemoteSignerCapabilities,\n RemoteSignerRequest,\n SignTransactionResponse,\n SignAllTransactionsResponse,\n SignMessageResponse,\n SignAndSendTransactionResponse,\n RemoteSignerErrorCode,\n RemoteSignerErrorResponse,\n} from '../remote/protocol';\nimport { decodeBase64, encodeBase64 } from '../remote/protocol';\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Signer interface that providers must implement\n */\nexport interface RemoteSigner {\n /** Signer's Solana address (base58) */\n readonly address: string;\n\n /** Sign transaction bytes, return signed transaction bytes */\n signTransaction(transactionBytes: Uint8Array): Promise<Uint8Array>;\n\n /** Sign multiple transactions */\n signAllTransactions(transactions: Uint8Array[]): Promise<Uint8Array[]>;\n\n /** Sign a message, return 64-byte signature */\n signMessage(message: Uint8Array): Promise<Uint8Array>;\n\n /** Check if signer is available/healthy */\n isAvailable(): Promise<boolean>;\n}\n\n/**\n * Provider configuration\n */\nexport type ProviderType = 'fireblocks' | 'privy' | 'custom';\n\nexport interface FireblocksProviderConfig {\n type: 'fireblocks';\n /** Fireblocks API key */\n apiKey: string;\n /** RSA private key PEM for JWT signing */\n privateKeyPem: string;\n /** Vault account ID */\n vaultAccountId: string;\n /** Asset ID (default: 'SOL') */\n assetId?: string;\n /** API base URL (default: https://api.fireblocks.io) */\n apiBaseUrl?: string;\n}\n\nexport interface PrivyProviderConfig {\n type: 'privy';\n /** Privy app ID */\n appId: string;\n /** Privy app secret */\n appSecret: string;\n /** Privy wallet ID */\n walletId: string;\n /** API base URL (default: https://api.privy.io/v1) */\n apiBaseUrl?: string;\n}\n\nexport interface CustomProviderConfig {\n type: 'custom';\n /** Custom signer implementation */\n signer: RemoteSigner;\n}\n\nexport type ProviderConfig = FireblocksProviderConfig | PrivyProviderConfig | CustomProviderConfig;\n\n/**\n * Authorization callback\n */\nexport type AuthorizeCallback = (request: Request) => Promise<boolean> | boolean;\n\n/**\n * Policy validation callback\n */\nexport interface PolicyHooks {\n /** Validate a transaction before signing (return false to reject) */\n validateTransaction?: (transactionBytes: Uint8Array, request: Request) => Promise<boolean> | boolean;\n /** Validate a message before signing (return false to reject) */\n validateMessage?: (messageBytes: Uint8Array, request: Request) => Promise<boolean> | boolean;\n}\n\n/**\n * RPC configuration for sign+send operations\n */\nexport interface RpcConfig {\n /** Solana RPC endpoint URL */\n url: string;\n /** Commitment level for confirmations */\n commitment?: 'processed' | 'confirmed' | 'finalized';\n}\n\n/**\n * Route handler configuration\n */\nexport interface RemoteSignerRouteHandlersConfig {\n /** Provider configuration */\n provider: ProviderConfig;\n /**\n * Authorization callback. Default: checks for Authorization header matching CONNECTOR_SIGNER_TOKEN env var.\n * Return true to allow, false to reject.\n */\n authorize?: AuthorizeCallback;\n /** Policy hooks for transaction/message validation */\n policy?: PolicyHooks;\n /** RPC configuration (required for signAndSendTransaction) */\n rpc?: RpcConfig;\n /** Supported chains (default: ['solana:mainnet', 'solana:devnet']) */\n chains?: string[];\n /** Wallet name shown in metadata */\n name?: string;\n /** Wallet icon URL */\n icon?: string;\n}\n\n/**\n * Next.js compatible request/response types\n */\nexport interface NextRequest extends Request {\n // Next.js adds extra properties, but we only need standard Request\n}\n\nexport type NextResponse = Response;\n\n/**\n * Route handlers object returned by the factory\n */\nexport interface RouteHandlers {\n GET: (request: NextRequest) => Promise<NextResponse>;\n POST: (request: NextRequest) => Promise<NextResponse>;\n}\n\n// ============================================================================\n// Helper functions\n// ============================================================================\n\nfunction jsonResponse(data: unknown, status = 200): Response {\n return new Response(JSON.stringify(data), {\n status,\n headers: { 'Content-Type': 'application/json' },\n });\n}\n\nfunction errorResponse(code: RemoteSignerErrorCode, message: string, status = 400, details?: unknown): Response {\n const body: RemoteSignerErrorResponse = {\n error: { code, message, details },\n };\n return jsonResponse(body, status);\n}\n\nfunction getEnv(name: string): string | undefined {\n return (globalThis as { process?: { env?: Record<string, string | undefined> } }).process?.env?.[name];\n}\n\n/**\n * Default authorization: check Authorization header against CONNECTOR_SIGNER_TOKEN env var\n */\nfunction defaultAuthorize(request: Request): boolean {\n const token = getEnv('CONNECTOR_SIGNER_TOKEN');\n if (!token) {\n // No token configured = reject all (safe default)\n console.warn('[connector/server] CONNECTOR_SIGNER_TOKEN not set - rejecting all requests');\n return false;\n }\n\n const authHeader = request.headers.get('Authorization');\n if (!authHeader) {\n return false;\n }\n\n // Support \"Bearer <token>\" format\n const parts = authHeader.split(' ');\n const providedToken = parts.length === 2 && parts[0].toLowerCase() === 'bearer' ? parts[1] : authHeader;\n\n return providedToken === token;\n}\n\n/**\n * Send a signed transaction to Solana RPC\n */\nasync function sendTransaction(rpc: RpcConfig, signedTxBytes: Uint8Array): Promise<string> {\n const base64Tx = encodeBase64(signedTxBytes);\n\n const response = await fetch(rpc.url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'sendTransaction',\n params: [\n base64Tx,\n {\n encoding: 'base64',\n skipPreflight: false,\n preflightCommitment: rpc.commitment || 'confirmed',\n },\n ],\n }),\n });\n\n const result = await response.json();\n\n if (result.error) {\n throw new Error(result.error.message || 'RPC error');\n }\n\n return result.result as string;\n}\n\n// ============================================================================\n// Provider loader\n// ============================================================================\n\nlet cachedSigner: RemoteSigner | null = null;\n\nasync function loadSigner(config: ProviderConfig): Promise<RemoteSigner> {\n if (cachedSigner) {\n return cachedSigner;\n }\n\n if (config.type === 'custom') {\n cachedSigner = config.signer;\n return cachedSigner;\n }\n\n if (config.type === 'fireblocks') {\n const { loadFireblocksSigner } = await import('./providers/fireblocks');\n cachedSigner = await loadFireblocksSigner(config);\n return cachedSigner;\n }\n\n if (config.type === 'privy') {\n const { loadPrivySigner } = await import('./providers/privy');\n cachedSigner = await loadPrivySigner(config);\n return cachedSigner;\n }\n\n throw new Error(`Unknown provider type: ${(config as ProviderConfig).type}`);\n}\n\n// ============================================================================\n// Route Handler Factory\n// ============================================================================\n\n/**\n * Create Next.js Route Handlers for remote signing\n *\n * @example\n * ```typescript\n * // app/api/connector-signer/route.ts\n * import { createRemoteSignerRouteHandlers } from '@solana/connector/server';\n *\n * const { GET, POST } = createRemoteSignerRouteHandlers({\n * provider: {\n * type: 'fireblocks',\n * apiKey: process.env.FIREBLOCKS_API_KEY!,\n * privateKeyPem: process.env.FIREBLOCKS_PRIVATE_KEY!,\n * vaultAccountId: process.env.FIREBLOCKS_VAULT_ID!,\n * },\n * rpc: {\n * url: process.env.SOLANA_RPC_URL!,\n * },\n * });\n *\n * export { GET, POST };\n * export const runtime = 'nodejs';\n * ```\n */\nexport function createRemoteSignerRouteHandlers(config: RemoteSignerRouteHandlersConfig): RouteHandlers {\n const {\n provider,\n authorize = defaultAuthorize,\n policy,\n rpc,\n chains = ['solana:mainnet', 'solana:devnet'],\n name = 'Remote Signer',\n icon,\n } = config;\n\n // GET handler: return signer metadata\n async function GET(request: NextRequest): Promise<NextResponse> {\n try {\n // Check authorization\n const authorized = await authorize(request);\n if (!authorized) {\n return errorResponse('UNAUTHORIZED', 'Unauthorized', 401);\n }\n\n // Load signer\n const signer = await loadSigner(provider);\n\n // Check availability\n const available = await signer.isAvailable();\n if (!available) {\n return errorResponse('PROVIDER_ERROR', 'Signer not available', 503);\n }\n\n // Build capabilities\n const capabilities: RemoteSignerCapabilities = {\n signTransaction: true,\n signAllTransactions: true,\n signMessage: true,\n signAndSendTransaction: Boolean(rpc),\n };\n\n // Build metadata response\n const metadata: RemoteSignerMetadata = {\n address: signer.address,\n chains,\n capabilities,\n name,\n icon,\n };\n\n return jsonResponse(metadata);\n } catch (error) {\n console.error('[connector/server] GET error:', error);\n return errorResponse(\n 'INTERNAL_ERROR',\n error instanceof Error ? error.message : 'Internal server error',\n 500,\n );\n }\n }\n\n // POST handler: handle signing operations\n async function POST(request: NextRequest): Promise<NextResponse> {\n try {\n // Check authorization\n const authorized = await authorize(request);\n if (!authorized) {\n return errorResponse('UNAUTHORIZED', 'Unauthorized', 401);\n }\n\n // Parse request body\n let body: RemoteSignerRequest;\n try {\n body = await request.json();\n } catch {\n return errorResponse('INVALID_REQUEST', 'Invalid JSON body', 400);\n }\n\n if (!body.operation) {\n return errorResponse('INVALID_REQUEST', 'Missing operation field', 400);\n }\n\n // Load signer\n const signer = await loadSigner(provider);\n\n // Handle operations\n switch (body.operation) {\n case 'signTransaction': {\n if (!body.transaction) {\n return errorResponse('INVALID_REQUEST', 'Missing transaction field', 400);\n }\n\n const txBytes = decodeBase64(body.transaction);\n\n // Policy check\n if (policy?.validateTransaction) {\n const allowed = await policy.validateTransaction(txBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Transaction rejected by policy', 403);\n }\n }\n\n const signedTx = await signer.signTransaction(txBytes);\n const response: SignTransactionResponse = {\n signedTransaction: encodeBase64(signedTx),\n };\n return jsonResponse(response);\n }\n\n case 'signAllTransactions': {\n if (!body.transactions || !Array.isArray(body.transactions)) {\n return errorResponse('INVALID_REQUEST', 'Missing transactions array', 400);\n }\n\n const txBytesArray = body.transactions.map(tx => decodeBase64(tx));\n\n // Policy check for each transaction\n if (policy?.validateTransaction) {\n for (const txBytes of txBytesArray) {\n const allowed = await policy.validateTransaction(txBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Transaction rejected by policy', 403);\n }\n }\n }\n\n const signedTxs = await signer.signAllTransactions(txBytesArray);\n const response: SignAllTransactionsResponse = {\n signedTransactions: signedTxs.map(tx => encodeBase64(tx)),\n };\n return jsonResponse(response);\n }\n\n case 'signMessage': {\n if (!body.message) {\n return errorResponse('INVALID_REQUEST', 'Missing message field', 400);\n }\n\n const messageBytes = decodeBase64(body.message);\n\n // Policy check\n if (policy?.validateMessage) {\n const allowed = await policy.validateMessage(messageBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Message rejected by policy', 403);\n }\n }\n\n const signature = await signer.signMessage(messageBytes);\n const response: SignMessageResponse = {\n signature: encodeBase64(signature),\n };\n return jsonResponse(response);\n }\n\n case 'signAndSendTransaction': {\n if (!rpc) {\n return errorResponse('INVALID_OPERATION', 'signAndSendTransaction not enabled', 400);\n }\n\n if (!body.transaction) {\n return errorResponse('INVALID_REQUEST', 'Missing transaction field', 400);\n }\n\n const txBytes = decodeBase64(body.transaction);\n\n // Policy check\n if (policy?.validateTransaction) {\n const allowed = await policy.validateTransaction(txBytes, request);\n if (!allowed) {\n return errorResponse('POLICY_VIOLATION', 'Transaction rejected by policy', 403);\n }\n }\n\n // Sign\n const signedTx = await signer.signTransaction(txBytes);\n\n // Send\n try {\n const signature = await sendTransaction(rpc, signedTx);\n const response: SignAndSendTransactionResponse = { signature };\n return jsonResponse(response);\n } catch (error) {\n return errorResponse(\n 'SEND_FAILED',\n error instanceof Error ? error.message : 'Failed to send transaction',\n 500,\n );\n }\n }\n\n default:\n return errorResponse(\n 'INVALID_OPERATION',\n `Unknown operation: ${(body as { operation: string }).operation}`,\n 400,\n );\n }\n } catch (error) {\n console.error('[connector/server] POST error:', error);\n\n // Check for known signer errors\n if (error instanceof Error) {\n if (error.message.includes('rate limit') || error.message.includes('429')) {\n return errorResponse('PROVIDER_ERROR', 'Rate limited, please retry', 429);\n }\n }\n\n return errorResponse('SIGNING_FAILED', error instanceof Error ? error.message : 'Signing failed', 500);\n }\n }\n\n return { GET, POST };\n}\n"]}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import
|
|
2
|
-
import React, { ReactNode } from 'react';
|
|
1
|
+
import React__default, { ReactNode } from 'react';
|
|
3
2
|
import * as _wallet_standard_base from '@wallet-standard/base';
|
|
4
3
|
import { Wallet, WalletAccount, IdentifierArray } from '@wallet-standard/base';
|
|
5
|
-
import {
|
|
4
|
+
import { T as TransactionActivity, g as TransactionActivityStatus, f as SolanaTransaction } from './transaction-signer-B3eCsMfI.js';
|
|
6
5
|
import { SolanaClusterId, SolanaCluster } from '@wallet-ui/core';
|
|
7
6
|
import { Address } from '@solana/addresses';
|
|
8
7
|
import { Signature } from '@solana/keys';
|
|
@@ -930,6 +929,14 @@ declare class ConnectorClient {
|
|
|
930
929
|
offAll(): void;
|
|
931
930
|
emitEvent(event: ConnectorEvent): void;
|
|
932
931
|
trackTransaction(activity: Omit<TransactionActivity, 'timestamp' | 'cluster'>): void;
|
|
932
|
+
/**
|
|
933
|
+
* Emit a pre-send transaction preview event for devtools.
|
|
934
|
+
*
|
|
935
|
+
* This does not sign or send the transaction. It exists so apps that do not
|
|
936
|
+
* use the connector transaction signer can still surface wire bytes in the
|
|
937
|
+
* debugger (e.g. to simulate before sending).
|
|
938
|
+
*/
|
|
939
|
+
previewTransaction(transaction: SolanaTransaction): void;
|
|
933
940
|
updateTransactionStatus(signature: string, status: TransactionActivity['status'], error?: string): void;
|
|
934
941
|
clearTransactionHistory(): void;
|
|
935
942
|
getHealth(): ConnectorHealth;
|
|
@@ -971,7 +978,7 @@ interface DefaultConfigOptions {
|
|
|
971
978
|
/** Maximum retry attempts for error recovery (default: 3) */
|
|
972
979
|
maxRetries?: number;
|
|
973
980
|
/** Custom error handler */
|
|
974
|
-
onError?: (error: Error, errorInfo:
|
|
981
|
+
onError?: (error: Error, errorInfo: React__default.ErrorInfo) => void;
|
|
975
982
|
/**
|
|
976
983
|
* Image proxy URL prefix for token images.
|
|
977
984
|
* When set, token image URLs will be transformed to: `${imageProxy}${encodeURIComponent(originalUrl)}`
|
|
@@ -1075,9 +1082,9 @@ interface ExtendedConnectorConfig extends ConnectorConfig {
|
|
|
1075
1082
|
/** Maximum retry attempts (default: 3) */
|
|
1076
1083
|
maxRetries?: number;
|
|
1077
1084
|
/** Custom error handler */
|
|
1078
|
-
onError?: (error: Error, errorInfo:
|
|
1085
|
+
onError?: (error: Error, errorInfo: React__default.ErrorInfo) => void;
|
|
1079
1086
|
/** Custom fallback component */
|
|
1080
|
-
fallback?: (error: Error, retry: () => void) =>
|
|
1087
|
+
fallback?: (error: Error, retry: () => void) => React__default.ReactNode;
|
|
1081
1088
|
};
|
|
1082
1089
|
/**
|
|
1083
1090
|
* Image proxy URL prefix for token images.
|
|
@@ -1206,7 +1213,7 @@ declare function ConnectorProvider({ children, config, mobile, }: {
|
|
|
1206
1213
|
children: ReactNode;
|
|
1207
1214
|
config?: ExtendedConnectorConfig;
|
|
1208
1215
|
mobile?: MobileWalletAdapterConfig;
|
|
1209
|
-
}):
|
|
1216
|
+
}): React__default.JSX.Element;
|
|
1210
1217
|
declare function useConnector(): ConnectorSnapshot;
|
|
1211
1218
|
declare function useConnectorClient(): ConnectorClient | null;
|
|
1212
1219
|
|
|
@@ -1617,4 +1624,4 @@ declare const ready: Promise<void>;
|
|
|
1617
1624
|
*/
|
|
1618
1625
|
declare function getWalletsRegistry(): WalletsRegistry;
|
|
1619
1626
|
|
|
1620
|
-
export { type
|
|
1627
|
+
export { type WalletError as $, type AccountAddress as A, type StorageOptions as B, ClipboardErrorType as C, type DefaultConfigOptions as D, type EnhancedStorageAccountOptions as E, type WalletConnectMetadata as F, type WalletConnectSignAllTransactionsParams as G, type WalletConnectSignAllTransactionsResult as H, INITIAL_WALLET_STATUS as I, type WalletConnectSignAndSendTransactionParams as J, type WalletConnectSignAndSendTransactionResult as K, type Listener as L, type MobileWalletAdapterConfig as M, type WalletConnectSignMessageParams as N, type WalletConnectSignMessageResult as O, type PersistedWalletState as P, type WalletConnectSignTransactionParams as Q, type RegisterMwaConfig as R, type SessionAccount as S, type WalletConnectSignTransactionResult as T, type WalletConnectSolanaAccount as U, type WalletConnectTransport as V, type WalletConnectConfig as W, type WalletConnector as X, type WalletConnectorId as Y, type WalletConnectorMetadata as Z, type WalletDisplayConfig as _, type AccountInfo as a, WalletErrorType as a0, type WalletInfo as a1, type WalletName as a2, type WalletSession as a3, type WalletStandardAccount as a4, type WalletStandardWallet as a5, type WalletStatus as a6, type WalletStatusConnected as a7, type WalletStatusConnecting as a8, type WalletStatusDisconnected as a9, isDevnetCluster as aA, isDisconnected as aB, isLocalCluster as aC, isMainnetCluster as aD, isStatusError as aE, isTestnetCluster as aF, isWalletConnectorId as aG, isWalletError as aH, isWalletName as aI, isWalletStatusError as aJ, ready as aK, toLegacyWalletState as aL, useConnector as aM, useConnectorClient as aN, type WalletStatusError as aa, copyAddressToClipboard as ab, copySignatureToClipboard as ac, copyToClipboard as ad, createConnectorId as ae, createSolanaClient as af, createWalletError as ag, getAddressUrl as ah, getBlockUrl as ai, getChainIdForWalletStandard as aj, getClusterChainId as ak, getClusterExplorerUrl as al, getClusterName as am, getClusterRpcUrl as an, getClusterType as ao, getDefaultConfig as ap, getDefaultMobileConfig as aq, getPublicSolanaRpcUrl as ar, getTokenUrl as as, getTransactionUrl as at, getWalletNameFromConnectorId as au, getWalletsRegistry as av, isAccountAddress as aw, isClipboardAvailable as ax, isConnected as ay, isConnecting as az, type ClipboardResult as b, type ClusterType as c, type CoinGeckoConfig as d, type ConnectOptions as e, ConnectorClient as f, type ConnectorConfig as g, type ConnectorDebugMetrics as h, type ConnectorDebugState as i, type ConnectorEvent as j, type ConnectorEventListener as k, type ConnectorHealth as l, ConnectorProvider as m, type ConnectorSnapshot as n, type ConnectorState as o, type CopyOptions as p, type CreateSolanaClientArgs as q, type EnhancedStorageClusterOptions as r, type EnhancedStorageWalletOptions as s, type EnhancedStorageWalletStateOptions as t, type ExtendedConnectorConfig as u, type ModifiedClusterUrl as v, type SimplifiedWalletConnectConfig as w, type SolanaClient as x, type SolanaClusterMoniker as y, type StorageAdapter as z };
|