bsv-mcp 0.3.0 → 0.3.2
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/CHANGELOG.md +17 -0
- package/README.md +123 -0
- package/dist/index.js +894 -146
- package/index.ts +61 -7
- package/package.json +1 -1
- package/tools/index.ts +12 -3
- package/tools/wallet/brc100.ts +25 -1
- package/tools/wallet/droplit.ts +124 -0
- package/tools/wallet/integratedWallet.ts +1 -3
- package/tools/wallet/revealDelegation.ts +74 -0
- package/tools/wallet/setupDroplit.ts +10 -16
- package/tools/wallet/tools.ts +8 -4
- package/test-mcp-server.ts +0 -179
package/dist/index.js
CHANGED
|
@@ -207971,9 +207971,9 @@ var require_vary = __commonJS((exports, module) => {
|
|
|
207971
207971
|
if (!field) {
|
|
207972
207972
|
throw new TypeError("field argument is required");
|
|
207973
207973
|
}
|
|
207974
|
-
var
|
|
207975
|
-
for (var j5 = 0;j5 <
|
|
207976
|
-
if (!FIELD_NAME_REGEXP.test(
|
|
207974
|
+
var fields2 = !Array.isArray(field) ? parse8(String(field)) : field;
|
|
207975
|
+
for (var j5 = 0;j5 < fields2.length; j5++) {
|
|
207976
|
+
if (!FIELD_NAME_REGEXP.test(fields2[j5])) {
|
|
207977
207977
|
throw new TypeError("field argument contains an invalid header name");
|
|
207978
207978
|
}
|
|
207979
207979
|
}
|
|
@@ -207982,14 +207982,14 @@ var require_vary = __commonJS((exports, module) => {
|
|
|
207982
207982
|
}
|
|
207983
207983
|
var val = header;
|
|
207984
207984
|
var vals = parse8(header.toLowerCase());
|
|
207985
|
-
if (
|
|
207985
|
+
if (fields2.indexOf("*") !== -1 || vals.indexOf("*") !== -1) {
|
|
207986
207986
|
return "*";
|
|
207987
207987
|
}
|
|
207988
|
-
for (var i = 0;i <
|
|
207989
|
-
var fld =
|
|
207988
|
+
for (var i = 0;i < fields2.length; i++) {
|
|
207989
|
+
var fld = fields2[i].toLowerCase();
|
|
207990
207990
|
if (vals.indexOf(fld) === -1) {
|
|
207991
207991
|
vals.push(fld);
|
|
207992
|
-
val = val ? val + ", " +
|
|
207992
|
+
val = val ? val + ", " + fields2[i] : fields2[i];
|
|
207993
207993
|
}
|
|
207994
207994
|
}
|
|
207995
207995
|
return val;
|
|
@@ -213168,13 +213168,13 @@ var require_StorageKnex = __commonJS((exports) => {
|
|
|
213168
213168
|
delete e2.certificateId;
|
|
213169
213169
|
if (e2.logger != null)
|
|
213170
213170
|
delete e2.logger;
|
|
213171
|
-
const
|
|
213171
|
+
const fields2 = e2.fields;
|
|
213172
213172
|
if (e2.fields != null)
|
|
213173
213173
|
delete e2.fields;
|
|
213174
213174
|
const [id] = await this.toDb(trx)("certificates").insert(e2);
|
|
213175
213175
|
certificate.certificateId = id;
|
|
213176
|
-
if (
|
|
213177
|
-
for (const field of
|
|
213176
|
+
if (fields2 != null) {
|
|
213177
|
+
for (const field of fields2) {
|
|
213178
213178
|
field.certificateId = id;
|
|
213179
213179
|
field.userId = certificate.userId;
|
|
213180
213180
|
await this.insertCertificateField(field, trx);
|
|
@@ -223156,7 +223156,7 @@ var require_timestamp2 = __commonJS((exports, module) => {
|
|
|
223156
223156
|
|
|
223157
223157
|
// node_modules/knex/lib/migrations/migrate/MigrationGenerator.js
|
|
223158
223158
|
var require_MigrationGenerator = __commonJS((exports, module) => {
|
|
223159
|
-
var __dirname = "/Users/satchmo/
|
|
223159
|
+
var __dirname = "/Users/satchmo/.codex/worktrees/agent-stack-mcp/node_modules/knex/lib/migrations/migrate";
|
|
223160
223160
|
var path6 = __require("path");
|
|
223161
223161
|
var { writeJsFileUsingTemplate } = require_template2();
|
|
223162
223162
|
var { getMergedConfig } = require_migrator_configuration_merger();
|
|
@@ -223863,7 +223863,7 @@ var require_seeder_configuration_merger = __commonJS((exports, module) => {
|
|
|
223863
223863
|
|
|
223864
223864
|
// node_modules/knex/lib/migrations/seed/Seeder.js
|
|
223865
223865
|
var require_Seeder = __commonJS((exports, module) => {
|
|
223866
|
-
var __dirname = "/Users/satchmo/
|
|
223866
|
+
var __dirname = "/Users/satchmo/.codex/worktrees/agent-stack-mcp/node_modules/knex/lib/migrations/seed";
|
|
223867
223867
|
var path6 = __require("path");
|
|
223868
223868
|
var { ensureDirectoryExists } = require_fs();
|
|
223869
223869
|
var { writeJsFileUsingTemplate } = require_template2();
|
|
@@ -227862,11 +227862,11 @@ var require_querycompiler = __commonJS((exports, module) => {
|
|
|
227862
227862
|
_preValidate() {
|
|
227863
227863
|
const method = this.method;
|
|
227864
227864
|
const verb = hasOwn(methodAliases, method) ? methodAliases[method] : method;
|
|
227865
|
-
const
|
|
227866
|
-
if (!
|
|
227865
|
+
const invalid2 = this.invalidClauses[verb];
|
|
227866
|
+
if (!invalid2)
|
|
227867
227867
|
return;
|
|
227868
|
-
for (let i = 0;i <
|
|
227869
|
-
const clause =
|
|
227868
|
+
for (let i = 0;i < invalid2.length; i++) {
|
|
227869
|
+
const clause = invalid2[i];
|
|
227870
227870
|
const hasNonEmptyGrouped = hasOwn(this.grouped, clause) && this.grouped[clause].length > 0;
|
|
227871
227871
|
const hasNonEmptySingle = hasOwn(this.single, clause) && this.single[clause] != null;
|
|
227872
227872
|
if (hasNonEmptyGrouped || hasNonEmptySingle) {
|
|
@@ -236146,10 +236146,10 @@ var require_mysql = __commonJS((exports, module) => {
|
|
|
236146
236146
|
return;
|
|
236147
236147
|
}
|
|
236148
236148
|
const queryOptions = Object.assign({ sql: obj.sql }, obj.options);
|
|
236149
|
-
connection.query(queryOptions, obj.bindings, function(err, rows,
|
|
236149
|
+
connection.query(queryOptions, obj.bindings, function(err, rows, fields2) {
|
|
236150
236150
|
if (err)
|
|
236151
236151
|
return rejecter(err);
|
|
236152
|
-
obj.response = [rows,
|
|
236152
|
+
obj.response = [rows, fields2];
|
|
236153
236153
|
resolver(obj);
|
|
236154
236154
|
});
|
|
236155
236155
|
});
|
|
@@ -236160,9 +236160,9 @@ var require_mysql = __commonJS((exports, module) => {
|
|
|
236160
236160
|
const { response } = obj;
|
|
236161
236161
|
const { method } = obj;
|
|
236162
236162
|
const rows = response[0];
|
|
236163
|
-
const
|
|
236163
|
+
const fields2 = response[1];
|
|
236164
236164
|
if (obj.output)
|
|
236165
|
-
return obj.output.call(runner, rows,
|
|
236165
|
+
return obj.output.call(runner, rows, fields2);
|
|
236166
236166
|
switch (method) {
|
|
236167
236167
|
case "select":
|
|
236168
236168
|
return rows;
|
|
@@ -236439,9 +236439,9 @@ var require_mariadb = __commonJS((exports, module) => {
|
|
|
236439
236439
|
return;
|
|
236440
236440
|
if (obj.returning) {
|
|
236441
236441
|
const rows = obj.response[0];
|
|
236442
|
-
const
|
|
236442
|
+
const fields2 = obj.response[1];
|
|
236443
236443
|
if (obj.output) {
|
|
236444
|
-
return obj.output.call(runner, rows,
|
|
236444
|
+
return obj.output.call(runner, rows, fields2);
|
|
236445
236445
|
}
|
|
236446
236446
|
return rows;
|
|
236447
236447
|
}
|
|
@@ -242385,8 +242385,8 @@ var require_ShamirWalletManager = __commonJS((exports) => {
|
|
|
242385
242385
|
await this.entropyCollector.collectFromBrowser(element, onProgress);
|
|
242386
242386
|
}
|
|
242387
242387
|
generateUserIdHash(privateKey) {
|
|
242388
|
-
const
|
|
242389
|
-
const hash2 = sdk_1.Hash.sha256(sdk_1.Utils.toArray(
|
|
242388
|
+
const publicKey2 = privateKey.toPublicKey().toString();
|
|
242389
|
+
const hash2 = sdk_1.Hash.sha256(sdk_1.Utils.toArray(publicKey2, "utf8"));
|
|
242390
242390
|
return sdk_1.Utils.toHex(hash2);
|
|
242391
242391
|
}
|
|
242392
242392
|
async createNewWallet(authPayload, onUserSharesReady) {
|
|
@@ -244852,13 +244852,13 @@ var init_storage_pg = __esm(() => {
|
|
|
244852
244852
|
e2.certificateId = undefined;
|
|
244853
244853
|
if (e2.logger)
|
|
244854
244854
|
e2.logger = undefined;
|
|
244855
|
-
const
|
|
244855
|
+
const fields2 = e2.fields;
|
|
244856
244856
|
if (e2.fields)
|
|
244857
244857
|
e2.fields = undefined;
|
|
244858
244858
|
const id = await this.insertRow("certificates", e2, trx);
|
|
244859
244859
|
certificate.certificateId = id;
|
|
244860
|
-
if (
|
|
244861
|
-
for (const field of
|
|
244860
|
+
if (fields2) {
|
|
244861
|
+
for (const field of fields2) {
|
|
244862
244862
|
field.certificateId = id;
|
|
244863
244863
|
field.userId = certificate.userId;
|
|
244864
244864
|
await this.insertCertificateField(field, trx);
|
|
@@ -256042,7 +256042,7 @@ var package_default = {
|
|
|
256042
256042
|
name: "bsv-mcp",
|
|
256043
256043
|
module: "dist/index.js",
|
|
256044
256044
|
type: "module",
|
|
256045
|
-
version: "0.3.
|
|
256045
|
+
version: "0.3.2",
|
|
256046
256046
|
license: "MIT",
|
|
256047
256047
|
author: "satchmo",
|
|
256048
256048
|
description: "A collection of Bitcoin SV (BSV) tools for the Model Context Protocol (MCP) framework",
|
|
@@ -284875,6 +284875,281 @@ function registerUtilsTools(server) {
|
|
|
284875
284875
|
});
|
|
284876
284876
|
}
|
|
284877
284877
|
|
|
284878
|
+
// utils/droplit.ts
|
|
284879
|
+
init_mod2();
|
|
284880
|
+
class DroplitError extends Error {
|
|
284881
|
+
code;
|
|
284882
|
+
status;
|
|
284883
|
+
details;
|
|
284884
|
+
constructor(code, message, status, details = {}) {
|
|
284885
|
+
super(message);
|
|
284886
|
+
this.code = code;
|
|
284887
|
+
this.status = status;
|
|
284888
|
+
this.details = details;
|
|
284889
|
+
}
|
|
284890
|
+
}
|
|
284891
|
+
function quotaDetails(body) {
|
|
284892
|
+
if (!body || typeof body !== "object")
|
|
284893
|
+
return {};
|
|
284894
|
+
const value2 = body;
|
|
284895
|
+
return {
|
|
284896
|
+
...typeof value2.remaining === "number" || value2.remaining === null ? { remaining: value2.remaining } : {},
|
|
284897
|
+
...typeof value2.resets_at === "string" ? { resets_at: value2.resets_at } : {}
|
|
284898
|
+
};
|
|
284899
|
+
}
|
|
284900
|
+
function httpFailure(status, details = {}) {
|
|
284901
|
+
const known = {
|
|
284902
|
+
401: [
|
|
284903
|
+
"authentication_required",
|
|
284904
|
+
"Authenticate with the configured wallet before retrying."
|
|
284905
|
+
],
|
|
284906
|
+
402: [
|
|
284907
|
+
"approval_required",
|
|
284908
|
+
"Payment is required. No automatic payment was made; review payment with the wallet owner."
|
|
284909
|
+
],
|
|
284910
|
+
403: [
|
|
284911
|
+
"approval_required",
|
|
284912
|
+
"The sponsor has not authorized this action. Ask its owner to approve your wallet."
|
|
284913
|
+
],
|
|
284914
|
+
429: [
|
|
284915
|
+
"quota_exceeded",
|
|
284916
|
+
"Sponsor quota exhausted. Wait until resets_at or ask the owner to adjust your quota."
|
|
284917
|
+
]
|
|
284918
|
+
};
|
|
284919
|
+
const [code, message] = known[status] ?? [
|
|
284920
|
+
"http_error",
|
|
284921
|
+
"Droplit rejected the request. Check sponsor access and transaction history before retrying."
|
|
284922
|
+
];
|
|
284923
|
+
return new DroplitError(code, message, status, details);
|
|
284924
|
+
}
|
|
284925
|
+
|
|
284926
|
+
class DroplitClient {
|
|
284927
|
+
config;
|
|
284928
|
+
authFetch;
|
|
284929
|
+
wallet;
|
|
284930
|
+
constructor(config2) {
|
|
284931
|
+
this.config = config2;
|
|
284932
|
+
if (config2.wallet && config2.authKey)
|
|
284933
|
+
throw new Error("Configure Droplit wallet or authKey, not both");
|
|
284934
|
+
const url3 = new URL(config2.apiUrl);
|
|
284935
|
+
const loopback = url3.hostname === "localhost" || url3.hostname === "127.0.0.1" || url3.hostname === "[::1]";
|
|
284936
|
+
if (url3.username || url3.password || url3.search || url3.hash || !(url3.protocol === "https:" || url3.protocol === "http:" && loopback)) {
|
|
284937
|
+
throw new Error("Droplit API requires HTTPS or HTTP loopback without credentials, query or fragment");
|
|
284938
|
+
}
|
|
284939
|
+
if (!config2.faucetName.trim())
|
|
284940
|
+
throw new Error("Droplit faucet name is required");
|
|
284941
|
+
this.wallet = config2.wallet ?? (config2.authKey ? new ProtoWallet_default(config2.authKey) : undefined);
|
|
284942
|
+
if (this.wallet) {
|
|
284943
|
+
const authenticationWallet = new Proxy(this.wallet, {
|
|
284944
|
+
get(target, property) {
|
|
284945
|
+
if (property === "createAction" || property === "signAction") {
|
|
284946
|
+
return async () => {
|
|
284947
|
+
throw httpFailure(402);
|
|
284948
|
+
};
|
|
284949
|
+
}
|
|
284950
|
+
const value2 = Reflect.get(target, property, target);
|
|
284951
|
+
return typeof value2 === "function" ? value2.bind(target) : value2;
|
|
284952
|
+
}
|
|
284953
|
+
});
|
|
284954
|
+
this.authFetch = new AuthFetch(authenticationWallet);
|
|
284955
|
+
}
|
|
284956
|
+
}
|
|
284957
|
+
getConfig() {
|
|
284958
|
+
return { apiUrl: this.config.apiUrl, faucetName: this.config.faucetName };
|
|
284959
|
+
}
|
|
284960
|
+
async getIdentityKey() {
|
|
284961
|
+
if (!this.wallet)
|
|
284962
|
+
throw new DroplitError("authentication_required", "Configure a Droplit wallet identity.");
|
|
284963
|
+
const { publicKey } = await this.wallet.getPublicKey({ identityKey: true });
|
|
284964
|
+
return publicKey;
|
|
284965
|
+
}
|
|
284966
|
+
get faucetPath() {
|
|
284967
|
+
return `/faucet/${encodeURIComponent(this.config.faucetName)}`;
|
|
284968
|
+
}
|
|
284969
|
+
get base() {
|
|
284970
|
+
return this.config.apiUrl.replace(/\/+$/, "");
|
|
284971
|
+
}
|
|
284972
|
+
async authed(path3, init) {
|
|
284973
|
+
if (!this.authFetch) {
|
|
284974
|
+
throw new Error(`${path3} requires authentication and no Droplit auth key is configured.`);
|
|
284975
|
+
}
|
|
284976
|
+
try {
|
|
284977
|
+
return await this.authFetch.fetch(`${this.base}${path3}`, {
|
|
284978
|
+
method: init.method,
|
|
284979
|
+
headers: { "Content-Type": "application/json" },
|
|
284980
|
+
...init.body === undefined ? {} : { body: JSON.stringify(init.body) },
|
|
284981
|
+
paymentRetryAttempts: 0,
|
|
284982
|
+
...init.method === "GET" || init.method === "HEAD" ? {} : { retryCounter: 1 }
|
|
284983
|
+
});
|
|
284984
|
+
} catch (error52) {
|
|
284985
|
+
if (error52 instanceof DroplitError)
|
|
284986
|
+
throw error52;
|
|
284987
|
+
const details = error52?.details;
|
|
284988
|
+
const status = details?.status;
|
|
284989
|
+
if (typeof status === "number" && [401, 402, 403, 429].includes(status)) {
|
|
284990
|
+
let body;
|
|
284991
|
+
if (status === 429 && typeof details?.bodyPreview === "string") {
|
|
284992
|
+
try {
|
|
284993
|
+
body = JSON.parse(details.bodyPreview);
|
|
284994
|
+
} catch {}
|
|
284995
|
+
}
|
|
284996
|
+
throw httpFailure(status, status === 429 ? quotaDetails(body) : {});
|
|
284997
|
+
}
|
|
284998
|
+
const write = init.method !== "GET" && init.method !== "HEAD";
|
|
284999
|
+
throw new DroplitError(write ? "unknown_outcome" : "request_failed", write ? "Request outcome is unknown. Reconcile transaction/history before retrying; no automatic retry was made." : "Authenticated request failed. Check the signer and sponsor connection.");
|
|
285000
|
+
}
|
|
285001
|
+
}
|
|
285002
|
+
async parse(response, _attempted) {
|
|
285003
|
+
if (response.ok) {
|
|
285004
|
+
try {
|
|
285005
|
+
return await response.json();
|
|
285006
|
+
} catch {
|
|
285007
|
+
throw new DroplitError("unknown_outcome", "Response could not be read. Reconcile transaction/history before retrying.", response.status);
|
|
285008
|
+
}
|
|
285009
|
+
}
|
|
285010
|
+
let body = {};
|
|
285011
|
+
try {
|
|
285012
|
+
body = await response.json();
|
|
285013
|
+
} catch {}
|
|
285014
|
+
throw httpFailure(response.status, response.status === 429 ? quotaDetails(body) : {});
|
|
285015
|
+
}
|
|
285016
|
+
async getAccess() {
|
|
285017
|
+
const response = await this.authed(`${this.faucetPath}/access`, {
|
|
285018
|
+
method: "GET"
|
|
285019
|
+
});
|
|
285020
|
+
const access = await this.parse(response, "Reading sponsor access");
|
|
285021
|
+
const identity6 = await this.getIdentityKey();
|
|
285022
|
+
if (!access || access.public_key !== identity6 || access.slug !== this.config.faucetName || typeof access.authorized !== "boolean" || typeof access.is_owner !== "boolean" || !Array.isArray(access.quotas) || !Array.isArray(access.unrestricted_kinds)) {
|
|
285023
|
+
throw new DroplitError("invalid_response", "Sponsor access response did not match the authenticated wallet.");
|
|
285024
|
+
}
|
|
285025
|
+
access.approval_path = `/droplit/${encodeURIComponent(this.config.faucetName)}?tab=api&request_key=${encodeURIComponent(identity6)}`;
|
|
285026
|
+
return access;
|
|
285027
|
+
}
|
|
285028
|
+
async fund(rawtx) {
|
|
285029
|
+
const response = await this.authed(`${this.faucetPath}/fund`, {
|
|
285030
|
+
method: "POST",
|
|
285031
|
+
body: { rawtx }
|
|
285032
|
+
});
|
|
285033
|
+
return this.parse(response, "Funding transaction");
|
|
285034
|
+
}
|
|
285035
|
+
async getFaucetStatus() {
|
|
285036
|
+
const response = await fetch(`${this.base}${this.faucetPath}/status`);
|
|
285037
|
+
return this.parse(response, "Reading the faucet status");
|
|
285038
|
+
}
|
|
285039
|
+
async tap(recipientAddress, satoshis) {
|
|
285040
|
+
if (satoshis !== undefined && (!Number.isSafeInteger(satoshis) || satoshis <= 0))
|
|
285041
|
+
throw new Error("satoshis must be a positive safe integer");
|
|
285042
|
+
const response = await this.authed(`${this.faucetPath}/tap`, {
|
|
285043
|
+
method: "POST",
|
|
285044
|
+
body: {
|
|
285045
|
+
recipient_address: recipientAddress,
|
|
285046
|
+
...satoshis === undefined ? {} : { satoshis }
|
|
285047
|
+
}
|
|
285048
|
+
});
|
|
285049
|
+
return this.parse(response, "Tapping the faucet");
|
|
285050
|
+
}
|
|
285051
|
+
async push(data, encoding = "hex") {
|
|
285052
|
+
const response = await this.authed(`${this.faucetPath}/push`, {
|
|
285053
|
+
method: "POST",
|
|
285054
|
+
body: { data, encoding }
|
|
285055
|
+
});
|
|
285056
|
+
return this.parse(response, "Pushing data");
|
|
285057
|
+
}
|
|
285058
|
+
async authenticatedFetch(path3, init) {
|
|
285059
|
+
return this.authed(path3, init);
|
|
285060
|
+
}
|
|
285061
|
+
}
|
|
285062
|
+
|
|
285063
|
+
// tools/wallet/droplit.ts
|
|
285064
|
+
function errorResult(error52) {
|
|
285065
|
+
const failure = error52 instanceof DroplitError ? error52 : new DroplitError("request_failed", "Droplit operation failed. Check configuration and broadcasting policy.");
|
|
285066
|
+
const data = {
|
|
285067
|
+
error: failure.code,
|
|
285068
|
+
message: failure.message,
|
|
285069
|
+
...failure.status === undefined ? {} : { status: failure.status },
|
|
285070
|
+
...failure.details
|
|
285071
|
+
};
|
|
285072
|
+
return {
|
|
285073
|
+
...createSuccessResponse(data),
|
|
285074
|
+
structuredContent: data,
|
|
285075
|
+
isError: true
|
|
285076
|
+
};
|
|
285077
|
+
}
|
|
285078
|
+
function registerDroplitTools(server, client, disableBroadcasting = false) {
|
|
285079
|
+
server.registerTool("droplit_getAccess", {
|
|
285080
|
+
description: "Read this connected wallet's sponsor authorization and quotas. If unauthorized, a human sponsor owner must approve the wallet manually. Does not create, fund, or approve anything.",
|
|
285081
|
+
inputSchema: {},
|
|
285082
|
+
annotations: {
|
|
285083
|
+
readOnlyHint: true,
|
|
285084
|
+
destructiveHint: false,
|
|
285085
|
+
idempotentHint: true,
|
|
285086
|
+
openWorldHint: true
|
|
285087
|
+
}
|
|
285088
|
+
}, async () => {
|
|
285089
|
+
try {
|
|
285090
|
+
const access = await client.getAccess();
|
|
285091
|
+
const data = {
|
|
285092
|
+
...access,
|
|
285093
|
+
...!access.authorized ? {
|
|
285094
|
+
error: "approval_required",
|
|
285095
|
+
message: "Ask the sponsor owner to approve this wallet. Copy the approval URL for manual review; do not auto-open or submit approval.",
|
|
285096
|
+
approval_url: `https://droplit.dev${access.approval_path}`
|
|
285097
|
+
} : {}
|
|
285098
|
+
};
|
|
285099
|
+
return {
|
|
285100
|
+
...createSuccessResponse(data),
|
|
285101
|
+
structuredContent: data,
|
|
285102
|
+
isError: !access.authorized
|
|
285103
|
+
};
|
|
285104
|
+
} catch (error52) {
|
|
285105
|
+
return errorResult(error52);
|
|
285106
|
+
}
|
|
285107
|
+
});
|
|
285108
|
+
server.registerTool("droplit_push", {
|
|
285109
|
+
description: "Submit one sponsored data transaction. Subject to sponsor approval and quotas. An unknown outcome requires checking transaction history before retrying.",
|
|
285110
|
+
inputSchema: {
|
|
285111
|
+
data: exports_external.array(exports_external.string()).min(1),
|
|
285112
|
+
encoding: exports_external.enum(["hex", "utf8"])
|
|
285113
|
+
},
|
|
285114
|
+
annotations: {
|
|
285115
|
+
readOnlyHint: false,
|
|
285116
|
+
destructiveHint: true,
|
|
285117
|
+
idempotentHint: false,
|
|
285118
|
+
openWorldHint: true
|
|
285119
|
+
}
|
|
285120
|
+
}, async ({ data, encoding }) => {
|
|
285121
|
+
try {
|
|
285122
|
+
if (disableBroadcasting)
|
|
285123
|
+
throw new Error("Broadcasting disabled");
|
|
285124
|
+
assertBroadcastAllowed("droplit_push");
|
|
285125
|
+
return createSuccessResponse(await client.push(data, encoding));
|
|
285126
|
+
} catch (error52) {
|
|
285127
|
+
return errorResult(error52);
|
|
285128
|
+
}
|
|
285129
|
+
});
|
|
285130
|
+
server.registerTool("droplit_fund", {
|
|
285131
|
+
description: "Submit one raw transaction for sponsor funding and broadcast. Subject to sponsor approval and quotas. Unknown outcomes must be reconciled before retrying.",
|
|
285132
|
+
inputSchema: {
|
|
285133
|
+
rawtx: exports_external.string().min(2).regex(/^(?:[0-9a-fA-F]{2})+$/, "Expected raw transaction hex")
|
|
285134
|
+
},
|
|
285135
|
+
annotations: {
|
|
285136
|
+
readOnlyHint: false,
|
|
285137
|
+
destructiveHint: true,
|
|
285138
|
+
idempotentHint: false,
|
|
285139
|
+
openWorldHint: true
|
|
285140
|
+
}
|
|
285141
|
+
}, async ({ rawtx }) => {
|
|
285142
|
+
try {
|
|
285143
|
+
if (disableBroadcasting)
|
|
285144
|
+
throw new Error("Broadcasting disabled");
|
|
285145
|
+
assertBroadcastAllowed("droplit_fund");
|
|
285146
|
+
return createSuccessResponse(await client.fund(rawtx));
|
|
285147
|
+
} catch (error52) {
|
|
285148
|
+
return errorResult(error52);
|
|
285149
|
+
}
|
|
285150
|
+
});
|
|
285151
|
+
}
|
|
285152
|
+
|
|
284878
285153
|
// tools/wallet/getBalanceDroplit.ts
|
|
284879
285154
|
function registerWalletGetBalanceDroplitTool(server, droplitClient) {
|
|
284880
285155
|
server.tool("wallet_getBalance", "Gets the current balance of the wallet (Droplit mode)", {}, async () => {
|
|
@@ -284911,16 +285186,13 @@ function registerWalletGetBalanceDroplitTool(server, droplitClient) {
|
|
|
284911
285186
|
}
|
|
284912
285187
|
|
|
284913
285188
|
// tools/wallet/setupDroplit.ts
|
|
284914
|
-
function requireDroplit(integratedWallet) {
|
|
285189
|
+
async function requireDroplit(integratedWallet) {
|
|
284915
285190
|
const client = integratedWallet.getDroplitClient();
|
|
284916
285191
|
if (!client) {
|
|
284917
285192
|
throw new Error("Droplit client is not configured. Set DROPLIT_API_URL and DROPLIT_FAUCET_NAME.");
|
|
284918
285193
|
}
|
|
284919
|
-
const { apiUrl
|
|
284920
|
-
|
|
284921
|
-
throw new Error("Droplit requests must be signed, but no auth key is configured.");
|
|
284922
|
-
}
|
|
284923
|
-
return { apiUrl, publicKeyHex: authKey.toPublicKey().toString(), client };
|
|
285194
|
+
const { apiUrl } = client.getConfig();
|
|
285195
|
+
return { apiUrl, publicKeyHex: await client.getIdentityKey(), client };
|
|
284924
285196
|
}
|
|
284925
285197
|
async function failIfNotOk(response, attempted) {
|
|
284926
285198
|
if (response.ok)
|
|
@@ -284928,9 +285200,9 @@ async function failIfNotOk(response, attempted) {
|
|
|
284928
285200
|
throw new Error(`${attempted} failed (${response.status}): ${await response.text()}`);
|
|
284929
285201
|
}
|
|
284930
285202
|
function registerSetupDroplitTools(server, integratedWallet) {
|
|
284931
|
-
server.tool("wallet_registerDroplitKey", "Registers
|
|
285203
|
+
server.tool("wallet_registerDroplitKey", "Registers public authentication material. Registration does not grant sponsor access; a sponsor owner must approve the wallet separately.", {}, async () => {
|
|
284932
285204
|
try {
|
|
284933
|
-
const { apiUrl, publicKeyHex } = requireDroplit(integratedWallet);
|
|
285205
|
+
const { apiUrl, publicKeyHex } = await requireDroplit(integratedWallet);
|
|
284934
285206
|
const response = await fetch(`${apiUrl}/auth/register`, {
|
|
284935
285207
|
method: "POST",
|
|
284936
285208
|
headers: { "Content-Type": "application/json" },
|
|
@@ -284945,13 +285217,13 @@ function registerSetupDroplitTools(server, integratedWallet) {
|
|
|
284945
285217
|
return createErrorResponse(error52);
|
|
284946
285218
|
}
|
|
284947
285219
|
});
|
|
284948
|
-
server.tool("wallet_createDroplitFaucet", "
|
|
285220
|
+
server.tool("wallet_createDroplitFaucet", "Creates a faucet owned by this wallet which must be funded before use. This does not provide free credit or approval for another sponsor.", {
|
|
284949
285221
|
faucetName: exports_external.string().min(1).describe("Identifier for the new faucet; must be unique"),
|
|
284950
285222
|
fixedDropSats: exports_external.number().int().positive().optional().describe("Satoshis paid out per tap. Server default applies if unset."),
|
|
284951
285223
|
maxConsolidationInputs: exports_external.number().int().positive().optional().describe("Cap on inputs the faucet consolidates in one transaction")
|
|
284952
285224
|
}, async ({ faucetName, fixedDropSats, maxConsolidationInputs }) => {
|
|
284953
285225
|
try {
|
|
284954
|
-
const { client } = requireDroplit(integratedWallet);
|
|
285226
|
+
const { client } = await requireDroplit(integratedWallet);
|
|
284955
285227
|
const body = {
|
|
284956
285228
|
name: faucetName,
|
|
284957
285229
|
...fixedDropSats !== undefined && {
|
|
@@ -284974,9 +285246,9 @@ function registerSetupDroplitTools(server, integratedWallet) {
|
|
|
284974
285246
|
return createErrorResponse(error52);
|
|
284975
285247
|
}
|
|
284976
285248
|
});
|
|
284977
|
-
server.tool("wallet_checkDroplitFaucetStatus", "Reads
|
|
285249
|
+
server.tool("wallet_checkDroplitFaucetStatus", "Reads public faucet balance and payout settings. This is not proof of caller authorization; use droplit_getAccess for that.", {}, async () => {
|
|
284978
285250
|
try {
|
|
284979
|
-
const { client } = requireDroplit(integratedWallet);
|
|
285251
|
+
const { client } = await requireDroplit(integratedWallet);
|
|
284980
285252
|
return createSuccessResponse({
|
|
284981
285253
|
faucetStatus: await client.getFaucetStatus()
|
|
284982
285254
|
});
|
|
@@ -294891,7 +295163,7 @@ var package_default2 = {
|
|
|
294891
295163
|
name: "bsv-mcp",
|
|
294892
295164
|
module: "dist/index.js",
|
|
294893
295165
|
type: "module",
|
|
294894
|
-
version: "0.3.
|
|
295166
|
+
version: "0.3.2",
|
|
294895
295167
|
license: "MIT",
|
|
294896
295168
|
author: "satchmo",
|
|
294897
295169
|
description: "A collection of Bitcoin SV (BSV) tools for the Model Context Protocol (MCP) framework",
|
|
@@ -295324,8 +295596,15 @@ function registerBrc100Tools(server, ctx) {
|
|
|
295324
295596
|
txJSON: exports_external.string().describe("JSON array of AtomicBEEF bytes"),
|
|
295325
295597
|
outputsJSON: exports_external.string().describe("JSON array of outputs to internalize"),
|
|
295326
295598
|
description: exports_external.string().describe("5-50 char description"),
|
|
295327
|
-
labelsJSON: exports_external.string().optional().describe("JSON array of label strings")
|
|
295328
|
-
|
|
295599
|
+
labelsJSON: exports_external.string().optional().describe("JSON array of label strings"),
|
|
295600
|
+
seekPermission: exports_external.boolean().optional()
|
|
295601
|
+
}, async ({
|
|
295602
|
+
txJSON,
|
|
295603
|
+
outputsJSON,
|
|
295604
|
+
description,
|
|
295605
|
+
labelsJSON,
|
|
295606
|
+
seekPermission
|
|
295607
|
+
}) => {
|
|
295329
295608
|
if (!ctx)
|
|
295330
295609
|
return noCtx;
|
|
295331
295610
|
try {
|
|
@@ -295333,6 +295612,7 @@ function registerBrc100Tools(server, ctx) {
|
|
|
295333
295612
|
tx: parseRequiredJSON("txJSON", txJSON),
|
|
295334
295613
|
outputs: parseRequiredJSON("outputsJSON", outputsJSON),
|
|
295335
295614
|
description,
|
|
295615
|
+
seekPermission,
|
|
295336
295616
|
labels: parseJSON("labelsJSON", labelsJSON)
|
|
295337
295617
|
}));
|
|
295338
295618
|
} catch (e2) {
|
|
@@ -295349,7 +295629,8 @@ function registerBrc100Tools(server, ctx) {
|
|
|
295349
295629
|
includeOutputs: exports_external.boolean().default(false),
|
|
295350
295630
|
includeOutputLockingScripts: exports_external.boolean().default(false),
|
|
295351
295631
|
limit: exports_external.number().default(25),
|
|
295352
|
-
offset: exports_external.number().default(0)
|
|
295632
|
+
offset: exports_external.number().default(0),
|
|
295633
|
+
seekPermission: exports_external.boolean().optional()
|
|
295353
295634
|
}, async ({ labelsJSON, ...rest }) => {
|
|
295354
295635
|
if (!ctx)
|
|
295355
295636
|
return noCtx;
|
|
@@ -295371,7 +295652,8 @@ function registerBrc100Tools(server, ctx) {
|
|
|
295371
295652
|
includeTags: exports_external.boolean().default(false),
|
|
295372
295653
|
includeLabels: exports_external.boolean().default(false),
|
|
295373
295654
|
limit: exports_external.number().default(25),
|
|
295374
|
-
offset: exports_external.number().default(0)
|
|
295655
|
+
offset: exports_external.number().default(0),
|
|
295656
|
+
seekPermission: exports_external.boolean().optional()
|
|
295375
295657
|
}, async ({ tagsJSON, ...rest }) => {
|
|
295376
295658
|
if (!ctx)
|
|
295377
295659
|
return noCtx;
|
|
@@ -295423,7 +295705,9 @@ function registerBrc100Tools(server, ctx) {
|
|
|
295423
295705
|
protocolIDJSON: exports_external.string().describe("JSON array [securityLevel, protocolString]"),
|
|
295424
295706
|
keyID: exports_external.string(),
|
|
295425
295707
|
counterparty: exports_external.string().optional(),
|
|
295426
|
-
privileged: exports_external.boolean().optional()
|
|
295708
|
+
privileged: exports_external.boolean().optional(),
|
|
295709
|
+
privilegedReason: exports_external.string().optional(),
|
|
295710
|
+
seekPermission: exports_external.boolean().optional()
|
|
295427
295711
|
}, async ({ protocolIDJSON, ...rest }) => {
|
|
295428
295712
|
if (!ctx)
|
|
295429
295713
|
return noCtx;
|
|
@@ -295441,7 +295725,9 @@ function registerBrc100Tools(server, ctx) {
|
|
|
295441
295725
|
protocolIDJSON: exports_external.string().describe("JSON array [securityLevel, protocolString]"),
|
|
295442
295726
|
keyID: exports_external.string(),
|
|
295443
295727
|
counterparty: exports_external.string().optional(),
|
|
295444
|
-
privileged: exports_external.boolean().optional()
|
|
295728
|
+
privileged: exports_external.boolean().optional(),
|
|
295729
|
+
privilegedReason: exports_external.string().optional(),
|
|
295730
|
+
seekPermission: exports_external.boolean().optional()
|
|
295445
295731
|
}, async ({ protocolIDJSON, ...rest }) => {
|
|
295446
295732
|
if (!ctx)
|
|
295447
295733
|
return noCtx;
|
|
@@ -295459,7 +295745,9 @@ function registerBrc100Tools(server, ctx) {
|
|
|
295459
295745
|
protocolIDJSON: exports_external.string().describe("JSON array [securityLevel, protocolString]"),
|
|
295460
295746
|
keyID: exports_external.string(),
|
|
295461
295747
|
counterparty: exports_external.string().optional(),
|
|
295462
|
-
privileged: exports_external.boolean().optional()
|
|
295748
|
+
privileged: exports_external.boolean().optional(),
|
|
295749
|
+
privilegedReason: exports_external.string().optional(),
|
|
295750
|
+
seekPermission: exports_external.boolean().optional()
|
|
295463
295751
|
}, async ({ protocolIDJSON, ...rest }) => {
|
|
295464
295752
|
if (!ctx)
|
|
295465
295753
|
return noCtx;
|
|
@@ -295478,7 +295766,9 @@ function registerBrc100Tools(server, ctx) {
|
|
|
295478
295766
|
protocolIDJSON: exports_external.string().describe("JSON array [securityLevel, protocolString]"),
|
|
295479
295767
|
keyID: exports_external.string(),
|
|
295480
295768
|
counterparty: exports_external.string().optional(),
|
|
295481
|
-
privileged: exports_external.boolean().optional()
|
|
295769
|
+
privileged: exports_external.boolean().optional(),
|
|
295770
|
+
privilegedReason: exports_external.string().optional(),
|
|
295771
|
+
seekPermission: exports_external.boolean().optional()
|
|
295482
295772
|
}, async ({ protocolIDJSON, ...rest }) => {
|
|
295483
295773
|
if (!ctx)
|
|
295484
295774
|
return noCtx;
|
|
@@ -295497,7 +295787,9 @@ function registerBrc100Tools(server, ctx) {
|
|
|
295497
295787
|
protocolIDJSON: exports_external.string().describe("JSON array [securityLevel, protocolString]"),
|
|
295498
295788
|
keyID: exports_external.string(),
|
|
295499
295789
|
counterparty: exports_external.string().optional(),
|
|
295500
|
-
privileged: exports_external.boolean().optional()
|
|
295790
|
+
privileged: exports_external.boolean().optional(),
|
|
295791
|
+
privilegedReason: exports_external.string().optional(),
|
|
295792
|
+
seekPermission: exports_external.boolean().optional()
|
|
295501
295793
|
}, async ({ protocolIDJSON, ...rest }) => {
|
|
295502
295794
|
if (!ctx)
|
|
295503
295795
|
return noCtx;
|
|
@@ -295518,7 +295810,9 @@ function registerBrc100Tools(server, ctx) {
|
|
|
295518
295810
|
keyID: exports_external.string(),
|
|
295519
295811
|
counterparty: exports_external.string().optional(),
|
|
295520
295812
|
forSelf: exports_external.boolean().optional(),
|
|
295521
|
-
privileged: exports_external.boolean().optional()
|
|
295813
|
+
privileged: exports_external.boolean().optional(),
|
|
295814
|
+
privilegedReason: exports_external.string().optional(),
|
|
295815
|
+
seekPermission: exports_external.boolean().optional()
|
|
295522
295816
|
}, async ({ protocolIDJSON, ...rest }) => {
|
|
295523
295817
|
if (!ctx)
|
|
295524
295818
|
return noCtx;
|
|
@@ -295645,7 +295939,8 @@ function registerBrc100Tools(server, ctx) {
|
|
|
295645
295939
|
server.tool("wallet_discoverByIdentityKey", "Discovers certificates issued to a given identity key.", {
|
|
295646
295940
|
identityKey: exports_external.string().describe("Identity public key hex"),
|
|
295647
295941
|
limit: exports_external.number().default(25),
|
|
295648
|
-
offset: exports_external.number().default(0)
|
|
295942
|
+
offset: exports_external.number().default(0),
|
|
295943
|
+
seekPermission: exports_external.boolean().optional()
|
|
295649
295944
|
}, async (args) => {
|
|
295650
295945
|
if (!ctx)
|
|
295651
295946
|
return noCtx;
|
|
@@ -295658,7 +295953,8 @@ function registerBrc100Tools(server, ctx) {
|
|
|
295658
295953
|
server.tool("wallet_discoverByAttributes", "Discovers certificates matching specific attributes.", {
|
|
295659
295954
|
attributesJSON: exports_external.string().describe("JSON object of attribute key/value pairs to match"),
|
|
295660
295955
|
limit: exports_external.number().default(25),
|
|
295661
|
-
offset: exports_external.number().default(0)
|
|
295956
|
+
offset: exports_external.number().default(0),
|
|
295957
|
+
seekPermission: exports_external.boolean().optional()
|
|
295662
295958
|
}, async ({ attributesJSON, ...rest }) => {
|
|
295663
295959
|
if (!ctx)
|
|
295664
295960
|
return noCtx;
|
|
@@ -296862,6 +297158,195 @@ function registerRefreshUtxosTool(server, ctx) {
|
|
|
296862
297158
|
});
|
|
296863
297159
|
}
|
|
296864
297160
|
|
|
297161
|
+
// utils/revealDelegation.ts
|
|
297162
|
+
init_mod2();
|
|
297163
|
+
var publicKey = exports_external.string().regex(/^(02|03)[a-f0-9]{64}$/);
|
|
297164
|
+
var base643 = exports_external.string().min(4).max(16384).regex(/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/);
|
|
297165
|
+
var fields = exports_external.record(exports_external.string().min(1).max(49), base643).refine((v7) => Object.keys(v7).length > 0 && Object.keys(v7).length <= 32);
|
|
297166
|
+
var handoffSchema = exports_external.object({
|
|
297167
|
+
certificate: exports_external.object({
|
|
297168
|
+
type: exports_external.literal("30kchAJIGfLxzCNloCJNLI3AtkgA8UbkxlXU2Cj4PpA="),
|
|
297169
|
+
serialNumber: base643.refine((v7) => Buffer.from(v7, "base64").length === 32),
|
|
297170
|
+
subject: publicKey,
|
|
297171
|
+
certifier: publicKey,
|
|
297172
|
+
revocationOutpoint: exports_external.string().regex(/^[a-f0-9]{64}\.\d{1,10}$/),
|
|
297173
|
+
signature: exports_external.string().regex(/^(?:[a-f0-9]{2}){8,72}$/),
|
|
297174
|
+
fields
|
|
297175
|
+
}).strict(),
|
|
297176
|
+
subjectKeyring: fields,
|
|
297177
|
+
revealTo: publicKey,
|
|
297178
|
+
revelationPath: exports_external.string().max(512)
|
|
297179
|
+
}).strict();
|
|
297180
|
+
|
|
297181
|
+
class RevelationError extends Error {
|
|
297182
|
+
code;
|
|
297183
|
+
status;
|
|
297184
|
+
constructor(code, message, status) {
|
|
297185
|
+
super(message);
|
|
297186
|
+
this.code = code;
|
|
297187
|
+
this.status = status;
|
|
297188
|
+
}
|
|
297189
|
+
}
|
|
297190
|
+
function invalid() {
|
|
297191
|
+
throw new RevelationError("invalid_handoff", "Provide a valid Sigma origin and the owner's BRC-169 handoff.");
|
|
297192
|
+
}
|
|
297193
|
+
function parseHandoff(origin, handoffJSON) {
|
|
297194
|
+
if (handoffJSON.length > 131072 || !/^https?:\/\/[^/?#\\]+\/?$/.test(origin))
|
|
297195
|
+
invalid();
|
|
297196
|
+
const url3 = new URL(origin);
|
|
297197
|
+
const loopback = ["localhost", "127.0.0.1", "[::1]"].includes(url3.hostname);
|
|
297198
|
+
if (url3.username || url3.password || url3.protocol !== "https:" && !(url3.protocol === "http:" && loopback))
|
|
297199
|
+
invalid();
|
|
297200
|
+
const h5 = handoffSchema.parse(JSON.parse(handoffJSON));
|
|
297201
|
+
for (const key of [
|
|
297202
|
+
h5.certificate.subject,
|
|
297203
|
+
h5.certificate.certifier,
|
|
297204
|
+
h5.revealTo
|
|
297205
|
+
]) {
|
|
297206
|
+
if (!PublicKey.fromString(key).validate())
|
|
297207
|
+
invalid();
|
|
297208
|
+
}
|
|
297209
|
+
const match = /^\/api\/agents\/([A-Za-z0-9_-]{1,128})\/delegations\/(.+)\/revelation$/.exec(h5.revelationPath);
|
|
297210
|
+
if (!match || decodeURIComponent(match[2]) !== h5.certificate.serialNumber)
|
|
297211
|
+
invalid();
|
|
297212
|
+
if (Object.keys(h5.subjectKeyring).sort().join(`
|
|
297213
|
+
`) !== Object.keys(h5.certificate.fields).sort().join(`
|
|
297214
|
+
`))
|
|
297215
|
+
invalid();
|
|
297216
|
+
return {
|
|
297217
|
+
h: h5,
|
|
297218
|
+
endpoint: `${url3.origin}/api/agents/${encodeURIComponent(match[1])}/delegations/${encodeURIComponent(h5.certificate.serialNumber)}/revelation`,
|
|
297219
|
+
origin: url3.origin
|
|
297220
|
+
};
|
|
297221
|
+
}
|
|
297222
|
+
async function revealDelegation(wallet5, sigmaOrigin, handoffJSON) {
|
|
297223
|
+
let input;
|
|
297224
|
+
try {
|
|
297225
|
+
input = parseHandoff(sigmaOrigin, handoffJSON);
|
|
297226
|
+
} catch {
|
|
297227
|
+
invalid();
|
|
297228
|
+
}
|
|
297229
|
+
const { h: h5, endpoint, origin } = input;
|
|
297230
|
+
const c6 = h5.certificate;
|
|
297231
|
+
try {
|
|
297232
|
+
const { publicKey: identity6 } = await wallet5.getPublicKey({
|
|
297233
|
+
identityKey: true
|
|
297234
|
+
});
|
|
297235
|
+
if (identity6 !== c6.subject)
|
|
297236
|
+
throw new RevelationError("subject_mismatch", "The connected wallet is not this delegation's subject.");
|
|
297237
|
+
const certificate = new Certificate(c6.type, c6.serialNumber, c6.subject, c6.certifier, c6.revocationOutpoint, c6.fields, c6.signature);
|
|
297238
|
+
if (!await certificate.verify())
|
|
297239
|
+
invalid();
|
|
297240
|
+
} catch (error53) {
|
|
297241
|
+
if (error53 instanceof RevelationError)
|
|
297242
|
+
throw error53;
|
|
297243
|
+
throw new RevelationError("invalid_certificate", "Could not verify the certificate and connected wallet identity.");
|
|
297244
|
+
}
|
|
297245
|
+
let keyring;
|
|
297246
|
+
try {
|
|
297247
|
+
await wallet5.acquireCertificate({
|
|
297248
|
+
...c6,
|
|
297249
|
+
acquisitionProtocol: "direct",
|
|
297250
|
+
keyringRevealer: "certifier",
|
|
297251
|
+
keyringForSubject: h5.subjectKeyring
|
|
297252
|
+
});
|
|
297253
|
+
const proof = await wallet5.proveCertificate({
|
|
297254
|
+
certificate: c6,
|
|
297255
|
+
fieldsToReveal: Object.keys(c6.fields),
|
|
297256
|
+
verifier: h5.revealTo
|
|
297257
|
+
});
|
|
297258
|
+
keyring = fields.parse(proof.keyringForVerifier);
|
|
297259
|
+
} catch {
|
|
297260
|
+
throw new RevelationError("wallet_proof_failed", "The wallet could not acquire or prove this delegation. Check its certificate store before retrying.");
|
|
297261
|
+
}
|
|
297262
|
+
return postRevelation(wallet5, origin, endpoint, keyring);
|
|
297263
|
+
}
|
|
297264
|
+
async function postRevelation(wallet5, origin, endpoint, keyring) {
|
|
297265
|
+
const guarded = new Proxy(wallet5, {
|
|
297266
|
+
get(target, property) {
|
|
297267
|
+
if (property === "createAction" || property === "signAction")
|
|
297268
|
+
return async () => {
|
|
297269
|
+
throw new RevelationError("payment_required", "Sigma revelation must not require a payment.", 402);
|
|
297270
|
+
};
|
|
297271
|
+
const value2 = Reflect.get(target, property, target);
|
|
297272
|
+
return typeof value2 === "function" ? value2.bind(target) : value2;
|
|
297273
|
+
}
|
|
297274
|
+
});
|
|
297275
|
+
let refusal;
|
|
297276
|
+
const guardedFetch = async (url3, init) => {
|
|
297277
|
+
if (String(url3) !== `${origin}/.well-known/auth` && String(url3) !== endpoint) {
|
|
297278
|
+
refusal = new RevelationError("unexpected_endpoint", "Sigma authentication requested an unexpected endpoint.");
|
|
297279
|
+
throw refusal;
|
|
297280
|
+
}
|
|
297281
|
+
const response = await fetch(url3, { ...init, redirect: "error" });
|
|
297282
|
+
if ([401, 402, 403, 409, 422, 429].includes(response.status)) {
|
|
297283
|
+
refusal = new RevelationError(response.status === 402 ? "payment_required" : "request_rejected", "Sigma rejected revelation. Check owner delegation status before retrying.", response.status);
|
|
297284
|
+
throw refusal;
|
|
297285
|
+
}
|
|
297286
|
+
return response;
|
|
297287
|
+
};
|
|
297288
|
+
const transport = new SimplifiedFetchTransport(origin, guardedFetch);
|
|
297289
|
+
const sessions = new SessionManager;
|
|
297290
|
+
const auth5 = new AuthFetch(guarded, undefined, sessions);
|
|
297291
|
+
const peer = new Peer(guarded, transport, undefined, sessions);
|
|
297292
|
+
try {
|
|
297293
|
+
await peer.ready;
|
|
297294
|
+
auth5.peers[origin] = { peer, pendingCertificateRequests: [] };
|
|
297295
|
+
const response = await auth5.fetch(endpoint, {
|
|
297296
|
+
method: "POST",
|
|
297297
|
+
headers: { "Content-Type": "application/json" },
|
|
297298
|
+
body: JSON.stringify({ keyring }),
|
|
297299
|
+
retryCounter: 1,
|
|
297300
|
+
paymentRetryAttempts: 1
|
|
297301
|
+
});
|
|
297302
|
+
if (!response.ok)
|
|
297303
|
+
throw new RevelationError("request_rejected", "Sigma rejected revelation. Check owner delegation status before retrying.", response.status);
|
|
297304
|
+
return { status: "revealed", httpStatus: response.status };
|
|
297305
|
+
} catch (error53) {
|
|
297306
|
+
if (refusal)
|
|
297307
|
+
throw refusal;
|
|
297308
|
+
if (error53 instanceof RevelationError)
|
|
297309
|
+
throw error53;
|
|
297310
|
+
throw new RevelationError("outcome_unknown", "Revelation was not confirmed. Ask the owner to refresh delegation status before retrying; no automatic replay was attempted.");
|
|
297311
|
+
}
|
|
297312
|
+
}
|
|
297313
|
+
|
|
297314
|
+
// tools/wallet/revealDelegation.ts
|
|
297315
|
+
function registerRevealDelegationTool(server, ctx) {
|
|
297316
|
+
server.registerTool("wallet_revealDelegation", {
|
|
297317
|
+
description: "Receive the human owner's BRC-169 certificate handoff, acquire and prove it with this connected agent wallet, and reveal its restrictions to the specified Sigma verifier. Imports a certificate and activates its existing delegation. Never pays, broadcasts, follows redirects, or retries an ambiguous POST. The subject keyring stays with the wallet.",
|
|
297318
|
+
inputSchema: {
|
|
297319
|
+
sigmaOrigin: exports_external.string().max(2048).describe("Explicit Sigma HTTPS origin, or HTTP loopback for local testing"),
|
|
297320
|
+
handoffJSON: exports_external.string().max(131072).describe("JSON package copied by the owner: certificate, subjectKeyring, revealTo, revelationPath")
|
|
297321
|
+
},
|
|
297322
|
+
annotations: {
|
|
297323
|
+
readOnlyHint: false,
|
|
297324
|
+
destructiveHint: false,
|
|
297325
|
+
idempotentHint: false,
|
|
297326
|
+
openWorldHint: true
|
|
297327
|
+
}
|
|
297328
|
+
}, async ({ sigmaOrigin, handoffJSON }) => {
|
|
297329
|
+
try {
|
|
297330
|
+
if (!ctx)
|
|
297331
|
+
throw new RevelationError("wallet_unavailable", "Connect the agent's existing wallet first.");
|
|
297332
|
+
const data = await revealDelegation(ctx.wallet, sigmaOrigin, handoffJSON);
|
|
297333
|
+
return { ...createSuccessResponse(data), structuredContent: data };
|
|
297334
|
+
} catch (error53) {
|
|
297335
|
+
const failure = error53 instanceof RevelationError ? error53 : new RevelationError("revelation_failed", "Delegation revelation failed. Check wallet and owner status before retrying.");
|
|
297336
|
+
const data = {
|
|
297337
|
+
error: failure.code,
|
|
297338
|
+
message: failure.message,
|
|
297339
|
+
...failure.status === undefined ? {} : { status: failure.status }
|
|
297340
|
+
};
|
|
297341
|
+
return {
|
|
297342
|
+
...createSuccessResponse(data),
|
|
297343
|
+
structuredContent: data,
|
|
297344
|
+
isError: true
|
|
297345
|
+
};
|
|
297346
|
+
}
|
|
297347
|
+
});
|
|
297348
|
+
}
|
|
297349
|
+
|
|
296865
297350
|
// tools/wallet/sendAllBsv.ts
|
|
296866
297351
|
var sendAllBsvArgsSchema = exports_external.object({
|
|
296867
297352
|
destination: exports_external.string().describe("Destination P2PKH address to send all funds to")
|
|
@@ -297365,14 +297850,17 @@ function registerWalletTools(server, wallet5, config2) {
|
|
|
297365
297850
|
registerRefreshUtxosTool(server, config2.ctx);
|
|
297366
297851
|
registerWalletGetBalanceTool(server, config2.ctx);
|
|
297367
297852
|
registerBrc100Tools(server, config2.ctx);
|
|
297368
|
-
|
|
297853
|
+
registerRevealDelegationTool(server, config2.ctx);
|
|
297854
|
+
if (config2.enableA2bTools && wallet5 && config2.identityPk) {
|
|
297369
297855
|
registerA2bPublishMcpTool(server, wallet5, config2.identityPk, {
|
|
297370
297856
|
disableBroadcasting: config2.disableBroadcasting
|
|
297371
297857
|
});
|
|
297372
297858
|
}
|
|
297373
297859
|
registerCreateOrdinalsTool(server, config2.ctx);
|
|
297374
|
-
|
|
297375
|
-
|
|
297860
|
+
if (wallet5) {
|
|
297861
|
+
registerGatherCollectionInfoTool(server, wallet5);
|
|
297862
|
+
registerMintCollectionTool(server, wallet5);
|
|
297863
|
+
}
|
|
297376
297864
|
registerGetOrdinalsTool(server, config2.ctx);
|
|
297377
297865
|
registerListTokensTool(server, config2.ctx);
|
|
297378
297866
|
registerGetBsv21BalancesTool(server, config2.ctx);
|
|
@@ -297412,7 +297900,7 @@ function registerAllTools(server, config2 = {}) {
|
|
|
297412
297900
|
if (enableA2bTools) {
|
|
297413
297901
|
registerA2bDiscoverTool(server);
|
|
297414
297902
|
}
|
|
297415
|
-
if (enableBapTools) {
|
|
297903
|
+
if (enableBapTools && (!config2.ctx || config2.wallet)) {
|
|
297416
297904
|
const bapConfig = {
|
|
297417
297905
|
disableBroadcasting: config2.disableBroadcasting,
|
|
297418
297906
|
identityPk: config2.identityPk,
|
|
@@ -297425,6 +297913,8 @@ function registerAllTools(server, config2 = {}) {
|
|
|
297425
297913
|
registerBsocialTools(server, { wallet: config2.wallet });
|
|
297426
297914
|
}
|
|
297427
297915
|
if (enableWalletTools) {
|
|
297916
|
+
if (config2.droplitClient)
|
|
297917
|
+
registerDroplitTools(server, config2.droplitClient, config2.disableBroadcasting);
|
|
297428
297918
|
if (config2.integratedWallet?.isDroplitMode) {
|
|
297429
297919
|
const droplitClient = config2.integratedWallet.getDroplitClient();
|
|
297430
297920
|
if (droplitClient) {
|
|
@@ -297434,7 +297924,7 @@ function registerAllTools(server, config2 = {}) {
|
|
|
297434
297924
|
}
|
|
297435
297925
|
console.error("Registered Droplit mode wallet tools");
|
|
297436
297926
|
}
|
|
297437
|
-
} else if (config2.wallet) {
|
|
297927
|
+
} else if (config2.wallet || config2.ctx) {
|
|
297438
297928
|
const walletToolOptions = {
|
|
297439
297929
|
disableBroadcasting: config2.disableBroadcasting === true,
|
|
297440
297930
|
enableA2bTools,
|
|
@@ -297444,7 +297934,7 @@ function registerAllTools(server, config2 = {}) {
|
|
|
297444
297934
|
registerWalletTools(server, config2.wallet, walletToolOptions);
|
|
297445
297935
|
}
|
|
297446
297936
|
}
|
|
297447
|
-
if (enableMneeTools) {
|
|
297937
|
+
if (enableMneeTools && (!config2.ctx || config2.wallet)) {
|
|
297448
297938
|
registerMneeTools(server);
|
|
297449
297939
|
}
|
|
297450
297940
|
}
|
|
@@ -297452,62 +297942,6 @@ function registerAllTools(server, config2 = {}) {
|
|
|
297452
297942
|
// tools/wallet/integratedWallet.ts
|
|
297453
297943
|
init_mod2();
|
|
297454
297944
|
|
|
297455
|
-
// utils/droplit.ts
|
|
297456
|
-
init_mod2();
|
|
297457
|
-
|
|
297458
|
-
class DroplitClient {
|
|
297459
|
-
config;
|
|
297460
|
-
authFetch;
|
|
297461
|
-
constructor(config2) {
|
|
297462
|
-
this.config = config2;
|
|
297463
|
-
if (config2.authKey) {
|
|
297464
|
-
this.authFetch = new AuthFetch(new ProtoWallet_default(config2.authKey));
|
|
297465
|
-
}
|
|
297466
|
-
}
|
|
297467
|
-
getConfig() {
|
|
297468
|
-
return this.config;
|
|
297469
|
-
}
|
|
297470
|
-
get base() {
|
|
297471
|
-
return this.config.apiUrl.replace(/\/+$/, "");
|
|
297472
|
-
}
|
|
297473
|
-
async authed(path5, init) {
|
|
297474
|
-
if (!this.authFetch) {
|
|
297475
|
-
throw new Error(`${path5} requires authentication and no Droplit auth key is configured.`);
|
|
297476
|
-
}
|
|
297477
|
-
return this.authFetch.fetch(`${this.base}${path5}`, {
|
|
297478
|
-
method: init.method,
|
|
297479
|
-
headers: { "Content-Type": "application/json" },
|
|
297480
|
-
...init.body === undefined ? {} : { body: JSON.stringify(init.body) }
|
|
297481
|
-
});
|
|
297482
|
-
}
|
|
297483
|
-
async parse(response, attempted) {
|
|
297484
|
-
if (response.ok)
|
|
297485
|
-
return await response.json();
|
|
297486
|
-
const raw = await response.text();
|
|
297487
|
-
let detail = raw.slice(0, 200);
|
|
297488
|
-
try {
|
|
297489
|
-
const parsed = JSON.parse(raw);
|
|
297490
|
-
detail = parsed.message ?? parsed.error ?? detail;
|
|
297491
|
-
} catch {}
|
|
297492
|
-
throw new Error(`${attempted} failed (${response.status}): ${detail}`);
|
|
297493
|
-
}
|
|
297494
|
-
async getFaucetStatus() {
|
|
297495
|
-
const response = await fetch(`${this.base}/faucet/${this.config.faucetName}/status`);
|
|
297496
|
-
return this.parse(response, "Reading the faucet status");
|
|
297497
|
-
}
|
|
297498
|
-
async tap(recipientAddress) {
|
|
297499
|
-
const response = await this.authed(`/faucet/${this.config.faucetName}/tap`, { method: "POST", body: { recipient_address: recipientAddress } });
|
|
297500
|
-
return this.parse(response, "Tapping the faucet");
|
|
297501
|
-
}
|
|
297502
|
-
async push(data, encoding = "hex") {
|
|
297503
|
-
const response = await this.authed(`/faucet/${this.config.faucetName}/push`, { method: "POST", body: { data, encoding } });
|
|
297504
|
-
return this.parse(response, "Pushing data");
|
|
297505
|
-
}
|
|
297506
|
-
async authenticatedFetch(path5, init) {
|
|
297507
|
-
return this.authed(path5, init);
|
|
297508
|
-
}
|
|
297509
|
-
}
|
|
297510
|
-
|
|
297511
297945
|
// tools/wallet/wallet.ts
|
|
297512
297946
|
init_mod2();
|
|
297513
297947
|
class Wallet {
|
|
@@ -297602,9 +298036,9 @@ class Wallet {
|
|
|
297602
298036
|
if (!currentPaymentKey) {
|
|
297603
298037
|
throw new Error("No payment key available to derive public key.");
|
|
297604
298038
|
}
|
|
297605
|
-
const
|
|
298039
|
+
const publicKey2 = currentPaymentKey.toPublicKey();
|
|
297606
298040
|
return {
|
|
297607
|
-
publicKey:
|
|
298041
|
+
publicKey: publicKey2.toDER("hex")
|
|
297608
298042
|
};
|
|
297609
298043
|
}
|
|
297610
298044
|
async sendToAddress(address, amountSatoshis) {
|
|
@@ -297706,7 +298140,7 @@ class IntegratedWallet {
|
|
|
297706
298140
|
}
|
|
297707
298141
|
async sendToAddress(address, satoshis) {
|
|
297708
298142
|
if (this.droplitClient) {
|
|
297709
|
-
const response = await this.droplitClient.tap(address);
|
|
298143
|
+
const response = await this.droplitClient.tap(address, satoshis);
|
|
297710
298144
|
return { txid: response.txid };
|
|
297711
298145
|
}
|
|
297712
298146
|
if (this.localWallet) {
|
|
@@ -297845,9 +298279,9 @@ class Wallet2 {
|
|
|
297845
298279
|
if (!currentPaymentKey) {
|
|
297846
298280
|
throw new Error("No payment key available to derive public key.");
|
|
297847
298281
|
}
|
|
297848
|
-
const
|
|
298282
|
+
const publicKey2 = currentPaymentKey.toPublicKey();
|
|
297849
298283
|
return {
|
|
297850
|
-
publicKey:
|
|
298284
|
+
publicKey: publicKey2.toDER("hex")
|
|
297851
298285
|
};
|
|
297852
298286
|
}
|
|
297853
298287
|
async sendToAddress(address, amountSatoshis) {
|
|
@@ -297912,6 +298346,245 @@ class Wallet2 {
|
|
|
297912
298346
|
}
|
|
297913
298347
|
}
|
|
297914
298348
|
|
|
298349
|
+
// utils/droplit.ts
|
|
298350
|
+
init_mod2();
|
|
298351
|
+
function readDroplitSponsorConfig(env = process.env) {
|
|
298352
|
+
const apiUrl = env.DROPLIT_API_URL;
|
|
298353
|
+
const faucetName = env.DROPLIT_FAUCET_NAME;
|
|
298354
|
+
if (apiUrl === undefined && faucetName === undefined)
|
|
298355
|
+
return;
|
|
298356
|
+
if (!apiUrl?.trim() || !faucetName?.trim()) {
|
|
298357
|
+
throw new Error("DROPLIT_API_URL and DROPLIT_FAUCET_NAME must both be explicitly configured");
|
|
298358
|
+
}
|
|
298359
|
+
return { apiUrl, faucetName };
|
|
298360
|
+
}
|
|
298361
|
+
|
|
298362
|
+
class DroplitError2 extends Error {
|
|
298363
|
+
code;
|
|
298364
|
+
status;
|
|
298365
|
+
details;
|
|
298366
|
+
constructor(code, message, status, details = {}) {
|
|
298367
|
+
super(message);
|
|
298368
|
+
this.code = code;
|
|
298369
|
+
this.status = status;
|
|
298370
|
+
this.details = details;
|
|
298371
|
+
}
|
|
298372
|
+
}
|
|
298373
|
+
function quotaDetails2(body) {
|
|
298374
|
+
if (!body || typeof body !== "object")
|
|
298375
|
+
return {};
|
|
298376
|
+
const value2 = body;
|
|
298377
|
+
return {
|
|
298378
|
+
...typeof value2.remaining === "number" || value2.remaining === null ? { remaining: value2.remaining } : {},
|
|
298379
|
+
...typeof value2.resets_at === "string" ? { resets_at: value2.resets_at } : {}
|
|
298380
|
+
};
|
|
298381
|
+
}
|
|
298382
|
+
function httpFailure2(status, details = {}) {
|
|
298383
|
+
const known = {
|
|
298384
|
+
401: [
|
|
298385
|
+
"authentication_required",
|
|
298386
|
+
"Authenticate with the configured wallet before retrying."
|
|
298387
|
+
],
|
|
298388
|
+
402: [
|
|
298389
|
+
"approval_required",
|
|
298390
|
+
"Payment is required. No automatic payment was made; review payment with the wallet owner."
|
|
298391
|
+
],
|
|
298392
|
+
403: [
|
|
298393
|
+
"approval_required",
|
|
298394
|
+
"The sponsor has not authorized this action. Ask its owner to approve your wallet."
|
|
298395
|
+
],
|
|
298396
|
+
429: [
|
|
298397
|
+
"quota_exceeded",
|
|
298398
|
+
"Sponsor quota exhausted. Wait until resets_at or ask the owner to adjust your quota."
|
|
298399
|
+
]
|
|
298400
|
+
};
|
|
298401
|
+
const [code, message] = known[status] ?? [
|
|
298402
|
+
"http_error",
|
|
298403
|
+
"Droplit rejected the request. Check sponsor access and transaction history before retrying."
|
|
298404
|
+
];
|
|
298405
|
+
return new DroplitError2(code, message, status, details);
|
|
298406
|
+
}
|
|
298407
|
+
|
|
298408
|
+
class DroplitClient2 {
|
|
298409
|
+
config;
|
|
298410
|
+
authFetch;
|
|
298411
|
+
wallet;
|
|
298412
|
+
constructor(config2) {
|
|
298413
|
+
this.config = config2;
|
|
298414
|
+
if (config2.wallet && config2.authKey)
|
|
298415
|
+
throw new Error("Configure Droplit wallet or authKey, not both");
|
|
298416
|
+
const url3 = new URL(config2.apiUrl);
|
|
298417
|
+
const loopback = url3.hostname === "localhost" || url3.hostname === "127.0.0.1" || url3.hostname === "[::1]";
|
|
298418
|
+
if (url3.username || url3.password || url3.search || url3.hash || !(url3.protocol === "https:" || url3.protocol === "http:" && loopback)) {
|
|
298419
|
+
throw new Error("Droplit API requires HTTPS or HTTP loopback without credentials, query or fragment");
|
|
298420
|
+
}
|
|
298421
|
+
if (!config2.faucetName.trim())
|
|
298422
|
+
throw new Error("Droplit faucet name is required");
|
|
298423
|
+
this.wallet = config2.wallet ?? (config2.authKey ? new ProtoWallet_default(config2.authKey) : undefined);
|
|
298424
|
+
if (this.wallet) {
|
|
298425
|
+
const authenticationWallet = new Proxy(this.wallet, {
|
|
298426
|
+
get(target, property) {
|
|
298427
|
+
if (property === "createAction" || property === "signAction") {
|
|
298428
|
+
return async () => {
|
|
298429
|
+
throw httpFailure2(402);
|
|
298430
|
+
};
|
|
298431
|
+
}
|
|
298432
|
+
const value2 = Reflect.get(target, property, target);
|
|
298433
|
+
return typeof value2 === "function" ? value2.bind(target) : value2;
|
|
298434
|
+
}
|
|
298435
|
+
});
|
|
298436
|
+
this.authFetch = new AuthFetch(authenticationWallet);
|
|
298437
|
+
}
|
|
298438
|
+
}
|
|
298439
|
+
getConfig() {
|
|
298440
|
+
return { apiUrl: this.config.apiUrl, faucetName: this.config.faucetName };
|
|
298441
|
+
}
|
|
298442
|
+
async getIdentityKey() {
|
|
298443
|
+
if (!this.wallet)
|
|
298444
|
+
throw new DroplitError2("authentication_required", "Configure a Droplit wallet identity.");
|
|
298445
|
+
const { publicKey: publicKey2 } = await this.wallet.getPublicKey({ identityKey: true });
|
|
298446
|
+
return publicKey2;
|
|
298447
|
+
}
|
|
298448
|
+
get faucetPath() {
|
|
298449
|
+
return `/faucet/${encodeURIComponent(this.config.faucetName)}`;
|
|
298450
|
+
}
|
|
298451
|
+
get base() {
|
|
298452
|
+
return this.config.apiUrl.replace(/\/+$/, "");
|
|
298453
|
+
}
|
|
298454
|
+
async authed(path5, init) {
|
|
298455
|
+
if (!this.authFetch) {
|
|
298456
|
+
throw new Error(`${path5} requires authentication and no Droplit auth key is configured.`);
|
|
298457
|
+
}
|
|
298458
|
+
try {
|
|
298459
|
+
return await this.authFetch.fetch(`${this.base}${path5}`, {
|
|
298460
|
+
method: init.method,
|
|
298461
|
+
headers: { "Content-Type": "application/json" },
|
|
298462
|
+
...init.body === undefined ? {} : { body: JSON.stringify(init.body) },
|
|
298463
|
+
paymentRetryAttempts: 0,
|
|
298464
|
+
...init.method === "GET" || init.method === "HEAD" ? {} : { retryCounter: 1 }
|
|
298465
|
+
});
|
|
298466
|
+
} catch (error53) {
|
|
298467
|
+
if (error53 instanceof DroplitError2)
|
|
298468
|
+
throw error53;
|
|
298469
|
+
const details = error53?.details;
|
|
298470
|
+
const status = details?.status;
|
|
298471
|
+
if (typeof status === "number" && [401, 402, 403, 429].includes(status)) {
|
|
298472
|
+
let body;
|
|
298473
|
+
if (status === 429 && typeof details?.bodyPreview === "string") {
|
|
298474
|
+
try {
|
|
298475
|
+
body = JSON.parse(details.bodyPreview);
|
|
298476
|
+
} catch {}
|
|
298477
|
+
}
|
|
298478
|
+
throw httpFailure2(status, status === 429 ? quotaDetails2(body) : {});
|
|
298479
|
+
}
|
|
298480
|
+
const write = init.method !== "GET" && init.method !== "HEAD";
|
|
298481
|
+
throw new DroplitError2(write ? "unknown_outcome" : "request_failed", write ? "Request outcome is unknown. Reconcile transaction/history before retrying; no automatic retry was made." : "Authenticated request failed. Check the signer and sponsor connection.");
|
|
298482
|
+
}
|
|
298483
|
+
}
|
|
298484
|
+
async parse(response, _attempted) {
|
|
298485
|
+
if (response.ok) {
|
|
298486
|
+
try {
|
|
298487
|
+
return await response.json();
|
|
298488
|
+
} catch {
|
|
298489
|
+
throw new DroplitError2("unknown_outcome", "Response could not be read. Reconcile transaction/history before retrying.", response.status);
|
|
298490
|
+
}
|
|
298491
|
+
}
|
|
298492
|
+
let body = {};
|
|
298493
|
+
try {
|
|
298494
|
+
body = await response.json();
|
|
298495
|
+
} catch {}
|
|
298496
|
+
throw httpFailure2(response.status, response.status === 429 ? quotaDetails2(body) : {});
|
|
298497
|
+
}
|
|
298498
|
+
async getAccess() {
|
|
298499
|
+
const response = await this.authed(`${this.faucetPath}/access`, {
|
|
298500
|
+
method: "GET"
|
|
298501
|
+
});
|
|
298502
|
+
const access = await this.parse(response, "Reading sponsor access");
|
|
298503
|
+
const identity6 = await this.getIdentityKey();
|
|
298504
|
+
if (!access || access.public_key !== identity6 || access.slug !== this.config.faucetName || typeof access.authorized !== "boolean" || typeof access.is_owner !== "boolean" || !Array.isArray(access.quotas) || !Array.isArray(access.unrestricted_kinds)) {
|
|
298505
|
+
throw new DroplitError2("invalid_response", "Sponsor access response did not match the authenticated wallet.");
|
|
298506
|
+
}
|
|
298507
|
+
access.approval_path = `/droplit/${encodeURIComponent(this.config.faucetName)}?tab=api&request_key=${encodeURIComponent(identity6)}`;
|
|
298508
|
+
return access;
|
|
298509
|
+
}
|
|
298510
|
+
async fund(rawtx) {
|
|
298511
|
+
const response = await this.authed(`${this.faucetPath}/fund`, {
|
|
298512
|
+
method: "POST",
|
|
298513
|
+
body: { rawtx }
|
|
298514
|
+
});
|
|
298515
|
+
return this.parse(response, "Funding transaction");
|
|
298516
|
+
}
|
|
298517
|
+
async getFaucetStatus() {
|
|
298518
|
+
const response = await fetch(`${this.base}${this.faucetPath}/status`);
|
|
298519
|
+
return this.parse(response, "Reading the faucet status");
|
|
298520
|
+
}
|
|
298521
|
+
async tap(recipientAddress, satoshis) {
|
|
298522
|
+
if (satoshis !== undefined && (!Number.isSafeInteger(satoshis) || satoshis <= 0))
|
|
298523
|
+
throw new Error("satoshis must be a positive safe integer");
|
|
298524
|
+
const response = await this.authed(`${this.faucetPath}/tap`, {
|
|
298525
|
+
method: "POST",
|
|
298526
|
+
body: {
|
|
298527
|
+
recipient_address: recipientAddress,
|
|
298528
|
+
...satoshis === undefined ? {} : { satoshis }
|
|
298529
|
+
}
|
|
298530
|
+
});
|
|
298531
|
+
return this.parse(response, "Tapping the faucet");
|
|
298532
|
+
}
|
|
298533
|
+
async push(data, encoding = "hex") {
|
|
298534
|
+
const response = await this.authed(`${this.faucetPath}/push`, {
|
|
298535
|
+
method: "POST",
|
|
298536
|
+
body: { data, encoding }
|
|
298537
|
+
});
|
|
298538
|
+
return this.parse(response, "Pushing data");
|
|
298539
|
+
}
|
|
298540
|
+
async authenticatedFetch(path5, init) {
|
|
298541
|
+
return this.authed(path5, init);
|
|
298542
|
+
}
|
|
298543
|
+
}
|
|
298544
|
+
|
|
298545
|
+
// utils/externalWalletConfig.ts
|
|
298546
|
+
function readExternalWalletConfig(env = process.env) {
|
|
298547
|
+
const raw = env.BRC100_WALLET_URL;
|
|
298548
|
+
if (raw === undefined) {
|
|
298549
|
+
if (env.BRC100_WALLET_ORIGINATOR !== undefined) {
|
|
298550
|
+
throw new Error("BRC100_WALLET_ORIGINATOR requires BRC100_WALLET_URL");
|
|
298551
|
+
}
|
|
298552
|
+
return;
|
|
298553
|
+
}
|
|
298554
|
+
for (const name of ["PRIVATE_KEY_WIF", "IDENTITY_KEY_WIF"]) {
|
|
298555
|
+
if (env[name] !== undefined) {
|
|
298556
|
+
throw new Error(`BRC100_WALLET_URL conflicts with ${name}; select one wallet identity`);
|
|
298557
|
+
}
|
|
298558
|
+
}
|
|
298559
|
+
if (env.USE_DROPLIT_API === "true") {
|
|
298560
|
+
throw new Error("BRC100_WALLET_URL conflicts with USE_DROPLIT_API");
|
|
298561
|
+
}
|
|
298562
|
+
let url3;
|
|
298563
|
+
try {
|
|
298564
|
+
url3 = new URL(raw);
|
|
298565
|
+
} catch {
|
|
298566
|
+
throw new Error("BRC100_WALLET_URL must be a valid signer RPC URL");
|
|
298567
|
+
}
|
|
298568
|
+
const loopback = url3.hostname === "localhost" || url3.hostname === "[::1]" || /^127\.(?:\d{1,3}\.){2}\d{1,3}$/.test(url3.hostname);
|
|
298569
|
+
if (!raw || raw !== raw.trim() || /[\\\s@?]/.test(raw) || url3.username || url3.password || raw.includes("#") || url3.search || !(url3.protocol === "https:" || url3.protocol === "http:" && loopback)) {
|
|
298570
|
+
throw new Error("BRC100_WALLET_URL requires HTTPS or HTTP loopback, without credentials, queries or fragments");
|
|
298571
|
+
}
|
|
298572
|
+
const originator = env.BRC100_WALLET_ORIGINATOR ?? "bsv-mcp.local";
|
|
298573
|
+
let origin;
|
|
298574
|
+
try {
|
|
298575
|
+
origin = new URL(originator.includes("://") ? originator : `http://${originator}`);
|
|
298576
|
+
} catch {
|
|
298577
|
+
throw new Error("BRC100_WALLET_ORIGINATOR must be a domain or HTTP(S) origin");
|
|
298578
|
+
}
|
|
298579
|
+
if (!originator || /[\s\\]/.test(originator) || originator.length >= 250 || !["http:", "https:"].includes(origin.protocol) || origin.username || origin.password || origin.pathname !== "/" || origin.search || /[#?@]/.test(originator) || !/^(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*|\[::1\])$/i.test(origin.hostname) || origin.hostname.toLowerCase() === "admin.bsv-mcp.internal") {
|
|
298580
|
+
throw new Error("BRC100_WALLET_ORIGINATOR must be a non-admin domain or HTTP(S) origin without credentials, path, query or fragment");
|
|
298581
|
+
}
|
|
298582
|
+
return { url: url3.toString().replace(/\/$/, ""), originator };
|
|
298583
|
+
}
|
|
298584
|
+
async function initializeKeysForWalletMode(external4, loadLocalKeys) {
|
|
298585
|
+
return external4 ? undefined : loadLocalKeys();
|
|
298586
|
+
}
|
|
298587
|
+
|
|
297915
298588
|
// node_modules/jose/dist/webapi/lib/buffer_utils.js
|
|
297916
298589
|
var encoder = new TextEncoder;
|
|
297917
298590
|
var decoder = new TextDecoder;
|
|
@@ -300720,13 +301393,13 @@ class StorageBunSqlite extends import_StorageProvider.StorageProvider {
|
|
|
300720
301393
|
e2.certificateId = undefined;
|
|
300721
301394
|
if (e2.logger)
|
|
300722
301395
|
e2.logger = undefined;
|
|
300723
|
-
const
|
|
301396
|
+
const fields2 = e2.fields;
|
|
300724
301397
|
if (e2.fields)
|
|
300725
301398
|
e2.fields = undefined;
|
|
300726
301399
|
const id = this.insertRow("certificates", e2);
|
|
300727
301400
|
certificate.certificateId = id;
|
|
300728
|
-
if (
|
|
300729
|
-
for (const field of
|
|
301401
|
+
if (fields2) {
|
|
301402
|
+
for (const field of fields2) {
|
|
300730
301403
|
field.certificateId = id;
|
|
300731
301404
|
field.userId = certificate.userId;
|
|
300732
301405
|
await this.insertCertificateField(field, trx);
|
|
@@ -301997,9 +302670,19 @@ async function buildLocalStorage(config2, baseOptions) {
|
|
|
301997
302670
|
init_storage_pg();
|
|
301998
302671
|
var import_wallet_toolbox2 = __toESM(require_src6(), 1);
|
|
301999
302672
|
|
|
302673
|
+
// node_modules/@1sat/wallet-remote/dist/index.js
|
|
302674
|
+
init_dist4();
|
|
302675
|
+
|
|
302676
|
+
// node_modules/@1sat/wallet-remote/dist/createRemoteWallet.js
|
|
302677
|
+
init_dist4();
|
|
302678
|
+
var import_index_client2 = __toESM(require_index_client5(), 1);
|
|
302679
|
+
|
|
302680
|
+
// node_modules/@1sat/wallet-remote/dist/index.js
|
|
302681
|
+
var import_index_client3 = __toESM(require_index_client5(), 1);
|
|
302682
|
+
|
|
302000
302683
|
// utils/walletInit.ts
|
|
302001
302684
|
init_mod2();
|
|
302002
|
-
var
|
|
302685
|
+
var import_index_client4 = __toESM(require_index_client5(), 1);
|
|
302003
302686
|
|
|
302004
302687
|
// utils/spendingApproval.ts
|
|
302005
302688
|
var serverInstance2 = null;
|
|
@@ -302096,7 +302779,7 @@ async function initWallet(privateKeyWif, chain = "main") {
|
|
|
302096
302779
|
activeRemote: process.env.REMOTE_STORAGE_URL ?? DEFAULT_REMOTE_STORAGE_URL,
|
|
302097
302780
|
storageIdentityKey: "bsv-mcp"
|
|
302098
302781
|
});
|
|
302099
|
-
const wpm = new
|
|
302782
|
+
const wpm = new import_index_client4.WalletPermissionsManager(result2.wallet, ADMIN_ORIGINATOR, {
|
|
302100
302783
|
seekProtocolPermissionsForSigning: false,
|
|
302101
302784
|
seekProtocolPermissionsForEncrypting: false,
|
|
302102
302785
|
seekProtocolPermissionsForHMAC: false,
|
|
@@ -302138,7 +302821,7 @@ async function initWallet(privateKeyWif, chain = "main") {
|
|
|
302138
302821
|
}).catch((err) => {
|
|
302139
302822
|
console.error("[wallet] message box sync failed:", err);
|
|
302140
302823
|
});
|
|
302141
|
-
activeResult =
|
|
302824
|
+
activeResult = result2;
|
|
302142
302825
|
return {
|
|
302143
302826
|
wallet: wpm,
|
|
302144
302827
|
services: result2.services,
|
|
@@ -302147,6 +302830,36 @@ async function initWallet(privateKeyWif, chain = "main") {
|
|
|
302147
302830
|
destroy: result2.destroy
|
|
302148
302831
|
};
|
|
302149
302832
|
}
|
|
302833
|
+
async function initExternalWallet(config2, chain = "main") {
|
|
302834
|
+
const httpClient = (input, init) => fetch(input, {
|
|
302835
|
+
...init,
|
|
302836
|
+
redirect: "error",
|
|
302837
|
+
signal: init?.signal ? AbortSignal.any([init.signal, AbortSignal.timeout(1e4)]) : AbortSignal.timeout(1e4)
|
|
302838
|
+
});
|
|
302839
|
+
const wallet7 = new HTTPWalletJSON(config2.originator, config2.url, httpClient);
|
|
302840
|
+
let identityKey;
|
|
302841
|
+
try {
|
|
302842
|
+
const identity6 = await wallet7.getPublicKey({ identityKey: true });
|
|
302843
|
+
if (!/^(02|03)[0-9a-f]{64}$/i.test(identity6.publicKey)) {
|
|
302844
|
+
throw new Error("Signer returned an invalid compressed identity public key");
|
|
302845
|
+
}
|
|
302846
|
+
PublicKey.fromString(identity6.publicKey);
|
|
302847
|
+
identityKey = identity6.publicKey;
|
|
302848
|
+
} catch (error53) {
|
|
302849
|
+
throw new Error("External BRC-100 signer readiness failed. Check BRC100_WALLET_URL and approve identity access in the signer. This must be SDK signer RPC, not 1sat serve wallet storage RPC. No local wallet was created.", { cause: error53 });
|
|
302850
|
+
}
|
|
302851
|
+
const services2 = new OneSatServices(chain, process.env.ONESAT_API_URL);
|
|
302852
|
+
const dataDir = join2(homedir(), ".bsv-mcp");
|
|
302853
|
+
const ctx = createContext(wallet7, {
|
|
302854
|
+
services: services2,
|
|
302855
|
+
chain,
|
|
302856
|
+
dataDir,
|
|
302857
|
+
log: (entry) => writeAuditLog(dataDir, entry)
|
|
302858
|
+
});
|
|
302859
|
+
const destroy = async () => {};
|
|
302860
|
+
activeResult = { destroy };
|
|
302861
|
+
return { wallet: wallet7, ctx, services: services2, identityKey, destroy };
|
|
302862
|
+
}
|
|
302150
302863
|
async function destroyWallet() {
|
|
302151
302864
|
if (activeResult) {
|
|
302152
302865
|
await activeResult.destroy();
|
|
@@ -302283,7 +302996,7 @@ async function initializeKeys() {
|
|
|
302283
302996
|
}
|
|
302284
302997
|
var APP_RESOURCE_URI = "ui://bsv-mcp/app.html";
|
|
302285
302998
|
var __appDirname = dirname2(fileURLToPath(import.meta.url));
|
|
302286
|
-
function registerMcpAppTools(server2,
|
|
302999
|
+
function registerMcpAppTools(server2, wallet7, ctx) {
|
|
302287
303000
|
K3(server2, "bsv_dashboard", {
|
|
302288
303001
|
title: "BSV Dashboard",
|
|
302289
303002
|
description: "Interactive BSV dashboard with Explorer, Wallet, and Ordinals tabs. Use this for any BSV-related query that benefits from visual display.",
|
|
@@ -302433,7 +303146,7 @@ function registerMcpAppTools(server2, wallet6, ctx) {
|
|
|
302433
303146
|
ui: { resourceUri: APP_RESOURCE_URI, visibility: ["app"] }
|
|
302434
303147
|
}
|
|
302435
303148
|
}, async () => {
|
|
302436
|
-
if (!ctx && !
|
|
303149
|
+
if (!ctx && !wallet7) {
|
|
302437
303150
|
return {
|
|
302438
303151
|
content: [
|
|
302439
303152
|
{
|
|
@@ -302465,9 +303178,9 @@ function registerMcpAppTools(server2, wallet6, ctx) {
|
|
|
302465
303178
|
const [txid = "", voutStr = "0"] = (o6.outpoint ?? "").split(".");
|
|
302466
303179
|
return { txid, vout: Number(voutStr), satoshis: o6.satoshis };
|
|
302467
303180
|
});
|
|
302468
|
-
} else if (
|
|
302469
|
-
address =
|
|
302470
|
-
const { paymentUtxos } = await
|
|
303181
|
+
} else if (wallet7) {
|
|
303182
|
+
address = wallet7.getAddress();
|
|
303183
|
+
const { paymentUtxos } = await wallet7.getUtxos();
|
|
302471
303184
|
for (const utxo of paymentUtxos) {
|
|
302472
303185
|
totalSatoshis += utxo.satoshis || 0;
|
|
302473
303186
|
}
|
|
@@ -302892,6 +303605,8 @@ Options:
|
|
|
302892
303605
|
Environment Variables:
|
|
302893
303606
|
TRANSPORT Transport mode: 'stdio' or 'http' (default: http)
|
|
302894
303607
|
PORT HTTP server port (default: 3000)
|
|
303608
|
+
BRC100_WALLET_URL Existing SDK HTTPWalletJSON signer RPC URL
|
|
303609
|
+
BRC100_WALLET_ORIGINATOR Signer permission origin (default: bsv-mcp.local)
|
|
302895
303610
|
PRIVATE_KEY_WIF Payment private key in WIF format
|
|
302896
303611
|
DISABLE_TOOLS Disable all tools (default: false)
|
|
302897
303612
|
DISABLE_WALLET_TOOLS Disable wallet tools (default: false)
|
|
@@ -302915,7 +303630,7 @@ Tool Categories:
|
|
|
302915
303630
|
|
|
302916
303631
|
Authentication:
|
|
302917
303632
|
- Most tools work without authentication
|
|
302918
|
-
- Wallet operations
|
|
303633
|
+
- Wallet operations use BRC100_WALLET_URL, PRIVATE_KEY_WIF or generated keys
|
|
302919
303634
|
- BAP/A2B tools require identity keys (generated via bap_generate tool)
|
|
302920
303635
|
`);
|
|
302921
303636
|
process.exit(0);
|
|
@@ -302924,11 +303639,31 @@ Authentication:
|
|
|
302924
303639
|
console.log(`${package_default.name} v${package_default.version}`);
|
|
302925
303640
|
process.exit(0);
|
|
302926
303641
|
}
|
|
302927
|
-
const
|
|
303642
|
+
const externalWallet = readExternalWalletConfig();
|
|
303643
|
+
const sponsorConfig = CONFIG.useDroplitApi ? undefined : readDroplitSponsorConfig();
|
|
303644
|
+
const keys = await initializeKeysForWalletMode(externalWallet, initializeKeys);
|
|
303645
|
+
const {
|
|
303646
|
+
payPk,
|
|
303647
|
+
identityPk,
|
|
303648
|
+
xprv,
|
|
303649
|
+
source: keySource
|
|
303650
|
+
} = keys ?? {
|
|
303651
|
+
payPk: undefined,
|
|
303652
|
+
identityPk: undefined,
|
|
303653
|
+
xprv: undefined,
|
|
303654
|
+
source: "external"
|
|
303655
|
+
};
|
|
302928
303656
|
const hasPersistentPayKey = keySource === "env" || keySource === "file" || keySource === "encrypted";
|
|
302929
303657
|
const hasPersistentIdentityKey = !!identityPk && (keySource === "file" || keySource === "encrypted");
|
|
302930
303658
|
const hasXprv = !!xprv && (keySource === "file" || keySource === "env" || keySource === "encrypted");
|
|
302931
303659
|
const effectiveConfig = { ...CONFIG };
|
|
303660
|
+
if (externalWallet) {
|
|
303661
|
+
effectiveConfig.loadBapTools = false;
|
|
303662
|
+
effectiveConfig.loadBsocialTools = false;
|
|
303663
|
+
effectiveConfig.loadMneeTools = false;
|
|
303664
|
+
effectiveConfig.loadA2bTools = false;
|
|
303665
|
+
logFunc2("External BRC-100 signer selected; local key loading and generation bypassed.");
|
|
303666
|
+
}
|
|
302932
303667
|
logFunc2(`
|
|
302933
303668
|
--- BSV MCP Server Configuration ---`);
|
|
302934
303669
|
logFunc2(`Server Version: ${package_default.version}`);
|
|
@@ -302939,8 +303674,8 @@ Environment Variables:`);
|
|
|
302939
303674
|
if (CONFIG.transportMode === "http") {
|
|
302940
303675
|
logFunc2(` PORT: ${process.env.PORT || "Not Set (3000 default)"}`);
|
|
302941
303676
|
}
|
|
302942
|
-
logFunc2(` PRIVATE_KEY_WIF: ${process.env.PRIVATE_KEY_WIF ? "Set (using env key)" : "Not Set (using file/generating)"}`);
|
|
302943
|
-
logFunc2(` IDENTITY_KEY_WIF: ${process.env.IDENTITY_KEY_WIF ? "Set (using env key)" : "Not Set (using file/generating)"}`);
|
|
303677
|
+
logFunc2(` PRIVATE_KEY_WIF: ${externalWallet ? "Unused (external signer)" : process.env.PRIVATE_KEY_WIF ? "Set (using env key)" : "Not Set (using file/generating)"}`);
|
|
303678
|
+
logFunc2(` IDENTITY_KEY_WIF: ${externalWallet ? "Unused (external signer)" : process.env.IDENTITY_KEY_WIF ? "Set (using env key)" : "Not Set (using file/generating)"}`);
|
|
302944
303679
|
if (process.env.BSV_MCP_PASSPHRASE) {
|
|
302945
303680
|
logFunc2(" BSV_MCP_PASSPHRASE: \x1B[31mDEPRECATED - Remove this!\x1B[0m");
|
|
302946
303681
|
}
|
|
@@ -302996,11 +303731,11 @@ Effective Component Status:`);
|
|
|
302996
303731
|
const a2bStatus = effectiveConfig.loadA2bTools ? "\x1B[32mEnabled\x1B[0m" : "\x1B[31mDisabled\x1B[0m";
|
|
302997
303732
|
const bapStatus = effectiveConfig.loadBapTools ? "\x1B[32mEnabled\x1B[0m" : "\x1B[31mDisabled\x1B[0m";
|
|
302998
303733
|
let payKeyNote = "";
|
|
302999
|
-
if (!hasPersistentPayKey) {
|
|
303734
|
+
if (!externalWallet && !hasPersistentPayKey) {
|
|
303000
303735
|
payKeyNote = " \x1B[33m(Using generated payPk)\x1B[0m";
|
|
303001
303736
|
}
|
|
303002
303737
|
let identityKeyNote = "";
|
|
303003
|
-
if (!hasPersistentIdentityKey) {
|
|
303738
|
+
if (!externalWallet && !hasPersistentIdentityKey) {
|
|
303004
303739
|
identityKeyNote = " \x1B[33m(Using generated identityPk)\x1B[0m";
|
|
303005
303740
|
}
|
|
303006
303741
|
logFunc2(` Wallet: ${walletStatus}${payKeyNote}`);
|
|
@@ -303017,12 +303752,20 @@ Effective Component Status:`);
|
|
|
303017
303752
|
}
|
|
303018
303753
|
logFunc2(`------------------------------------
|
|
303019
303754
|
`);
|
|
303020
|
-
let
|
|
303755
|
+
let wallet7;
|
|
303021
303756
|
let integratedWallet;
|
|
303022
303757
|
let remoteCtx;
|
|
303023
303758
|
let remoteServices;
|
|
303024
303759
|
if (CONFIG.loadTools) {
|
|
303025
|
-
if (
|
|
303760
|
+
if (externalWallet) {
|
|
303761
|
+
const chain = process.env.BSV_CHAIN ?? "main";
|
|
303762
|
+
if (chain !== "main" && chain !== "test")
|
|
303763
|
+
throw new Error("BSV_CHAIN must be main or test");
|
|
303764
|
+
const result2 = await initExternalWallet(externalWallet, chain);
|
|
303765
|
+
remoteCtx = result2.ctx;
|
|
303766
|
+
remoteServices = result2.services;
|
|
303767
|
+
logFunc2(`External BRC-100 signer ready. Identity: ${result2.identityKey}`);
|
|
303768
|
+
} else if (CONFIG.useDroplitApi && CONFIG.droplitFaucetName) {
|
|
303026
303769
|
if (CONFIG.loadWalletTools) {
|
|
303027
303770
|
try {
|
|
303028
303771
|
integratedWallet = new IntegratedWallet({
|
|
@@ -303037,7 +303780,7 @@ Effective Component Status:`);
|
|
|
303037
303780
|
logFunc2(`\x1B[32mINFO: Droplit API mode initialized successfully (Faucet: ${CONFIG.droplitFaucetName}).\x1B[0m`);
|
|
303038
303781
|
logFunc2(`\x1B[33mNOTE: Using Droplit API at ${CONFIG.droplitApiUrl}\x1B[0m`);
|
|
303039
303782
|
logFunc2("\x1B[33mNOTE: Local keys are ignored in Droplit API mode\x1B[0m");
|
|
303040
|
-
|
|
303783
|
+
wallet7 = integratedWallet.getLocalWallet();
|
|
303041
303784
|
effectiveConfig.loadMneeTools = false;
|
|
303042
303785
|
effectiveConfig.loadBapTools = false;
|
|
303043
303786
|
effectiveConfig.loadA2bTools = false;
|
|
@@ -303053,7 +303796,7 @@ Effective Component Status:`);
|
|
|
303053
303796
|
} else if (payPk) {
|
|
303054
303797
|
if (CONFIG.loadWalletTools) {
|
|
303055
303798
|
try {
|
|
303056
|
-
|
|
303799
|
+
wallet7 = new Wallet2(payPk, identityPk);
|
|
303057
303800
|
integratedWallet = new IntegratedWallet({
|
|
303058
303801
|
paymentKey: payPk,
|
|
303059
303802
|
identityKey: identityPk
|
|
@@ -303067,7 +303810,7 @@ Effective Component Status:`);
|
|
|
303067
303810
|
}
|
|
303068
303811
|
} catch (e2) {
|
|
303069
303812
|
logFunc2(`\x1B[31mERROR: Failed to initialize custom wallet: ${e2 instanceof Error ? e2.message : String(e2)}. Wallet-dependent tools will be unavailable.\x1B[0m`);
|
|
303070
|
-
|
|
303813
|
+
wallet7 = undefined;
|
|
303071
303814
|
integratedWallet = undefined;
|
|
303072
303815
|
effectiveConfig.loadWalletTools = false;
|
|
303073
303816
|
effectiveConfig.loadMneeTools = false;
|
|
@@ -303083,12 +303826,16 @@ Effective Component Status:`);
|
|
|
303083
303826
|
logFunc2(`\x1B[33mWARN: Remote BRC-100 wallet initialization failed: ${e2 instanceof Error ? e2.message : String(e2)}. Falling back to local wallet only.\x1B[0m`);
|
|
303084
303827
|
}
|
|
303085
303828
|
}
|
|
303086
|
-
if (effectiveConfig.loadMneeTools && !
|
|
303829
|
+
if (effectiveConfig.loadMneeTools && !wallet7 && CONFIG.loadWalletTools) {
|
|
303087
303830
|
logFunc2("\x1B[33mWARN: MNEE tools require a wallet but wallet initialization failed. MNEE tools disabled.\x1B[0m");
|
|
303088
303831
|
effectiveConfig.loadMneeTools = false;
|
|
303089
303832
|
}
|
|
303090
303833
|
}
|
|
303091
303834
|
}
|
|
303835
|
+
const droplitClient = sponsorConfig && remoteCtx ? new DroplitClient2({ ...sponsorConfig, wallet: remoteCtx.wallet }) : undefined;
|
|
303836
|
+
if (sponsorConfig && CONFIG.loadTools && !remoteCtx) {
|
|
303837
|
+
throw new Error("Configured Droplit sponsor requires an initialized BRC-100 wallet context");
|
|
303838
|
+
}
|
|
303092
303839
|
const toolsConfig = CONFIG.loadTools ? {
|
|
303093
303840
|
enableBsvTools: effectiveConfig.loadBsvTools,
|
|
303094
303841
|
enableOrdinalsTools: effectiveConfig.loadOrdinalsTools,
|
|
@@ -303101,11 +303848,12 @@ Effective Component Status:`);
|
|
|
303101
303848
|
identityPk,
|
|
303102
303849
|
payPk,
|
|
303103
303850
|
xprv,
|
|
303104
|
-
wallet:
|
|
303851
|
+
wallet: wallet7,
|
|
303105
303852
|
integratedWallet,
|
|
303106
303853
|
disableBroadcasting: effectiveConfig.disableBroadcasting,
|
|
303107
303854
|
ctx: remoteCtx,
|
|
303108
|
-
services: remoteServices
|
|
303855
|
+
services: remoteServices,
|
|
303856
|
+
droplitClient
|
|
303109
303857
|
} : {
|
|
303110
303858
|
enableBsvTools: false,
|
|
303111
303859
|
enableOrdinalsTools: false,
|
|
@@ -303119,7 +303867,7 @@ Effective Component Status:`);
|
|
|
303119
303867
|
};
|
|
303120
303868
|
const serverFactoryOpts = {
|
|
303121
303869
|
toolsConfig,
|
|
303122
|
-
wallet:
|
|
303870
|
+
wallet: wallet7,
|
|
303123
303871
|
ctx: remoteCtx,
|
|
303124
303872
|
loadPrompts: effectiveConfig.loadPrompts,
|
|
303125
303873
|
loadResources: effectiveConfig.loadResources
|