@toon-protocol/client-mcp 0.8.2 → 0.8.3
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/app/index.html +91 -66
- package/dist/{chunk-57G7AAEG.js → chunk-C276YR4L.js} +59 -4
- package/dist/chunk-C276YR4L.js.map +1 -0
- package/dist/{chunk-G5H3OD5N.js → chunk-XJI66XFQ.js} +20 -3
- package/dist/chunk-XJI66XFQ.js.map +1 -0
- package/dist/{chunk-UEP6PFZN.js → chunk-ZVFLRFXS.js} +163 -12
- package/dist/chunk-ZVFLRFXS.js.map +1 -0
- package/dist/daemon.js +2 -2
- package/dist/index.d.ts +31 -1
- package/dist/index.js +3 -3
- package/dist/mcp.js +2 -2
- package/package.json +3 -3
- package/dist/chunk-57G7AAEG.js.map +0 -1
- package/dist/chunk-G5H3OD5N.js.map +0 -1
- package/dist/chunk-UEP6PFZN.js.map +0 -1
|
@@ -6524,6 +6524,7 @@ import {
|
|
|
6524
6524
|
import { privateKeyToAccount as privateKeyToAccount2 } from "viem/accounts";
|
|
6525
6525
|
import { toHex as toHex3 } from "viem";
|
|
6526
6526
|
import { readFileSync, writeFileSync, existsSync } from "fs";
|
|
6527
|
+
import { createPublicClient as createPublicClient2, http as http2, defineChain as defineChain2 } from "viem";
|
|
6527
6528
|
import { finalizeEvent as finalizeEvent22 } from "nostr-tools/pure";
|
|
6528
6529
|
import { nip19 } from "nostr-tools";
|
|
6529
6530
|
import { getPublicKey as getPublicKey32 } from "nostr-tools/pure";
|
|
@@ -8066,17 +8067,17 @@ function readDiscoveredIlpPeer(peer) {
|
|
|
8066
8067
|
}
|
|
8067
8068
|
function selectIlpTransport(peer, options = {}) {
|
|
8068
8069
|
const needsDuplex = options.needsDuplex ?? false;
|
|
8069
|
-
const
|
|
8070
|
+
const http3 = peer.httpEndpoint?.trim() || void 0;
|
|
8070
8071
|
const btp = peer.btpEndpoint?.trim() || void 0;
|
|
8071
8072
|
const canUpgrade = peer.supportsUpgrade === true;
|
|
8072
8073
|
if (needsDuplex) {
|
|
8073
8074
|
if (btp) return { kind: "btp", btpEndpoint: btp };
|
|
8074
|
-
if (
|
|
8075
|
+
if (http3 && canUpgrade) return { kind: "http-upgradable", httpEndpoint: http3 };
|
|
8075
8076
|
throw new Error(
|
|
8076
8077
|
"Duplex transport required but peer exposes neither a btpEndpoint nor an upgradable httpEndpoint"
|
|
8077
8078
|
);
|
|
8078
8079
|
}
|
|
8079
|
-
if (
|
|
8080
|
+
if (http3) return { kind: "http", httpEndpoint: http3, canUpgrade };
|
|
8080
8081
|
if (btp) return { kind: "btp", btpEndpoint: btp };
|
|
8081
8082
|
throw new Error("Peer exposes neither an httpEndpoint nor a btpEndpoint");
|
|
8082
8083
|
}
|
|
@@ -9870,6 +9871,18 @@ var ChannelManager = class {
|
|
|
9870
9871
|
}
|
|
9871
9872
|
return tracking.cumulativeAmount;
|
|
9872
9873
|
}
|
|
9874
|
+
/**
|
|
9875
|
+
* Gets the on-chain deposit total (collateral locked at open / via deposits)
|
|
9876
|
+
* for a tracked channel, or `0n` when none was captured. The available
|
|
9877
|
+
* (spendable) balance is `depositTotal - cumulativeAmount`.
|
|
9878
|
+
*/
|
|
9879
|
+
getDepositTotal(channelId) {
|
|
9880
|
+
const tracking = this.channels.get(channelId);
|
|
9881
|
+
if (!tracking) {
|
|
9882
|
+
throw new Error(`Channel "${channelId}" is not being tracked.`);
|
|
9883
|
+
}
|
|
9884
|
+
return tracking.depositTotal ?? 0n;
|
|
9885
|
+
}
|
|
9873
9886
|
/**
|
|
9874
9887
|
* Gets all tracked channel IDs.
|
|
9875
9888
|
*/
|
|
@@ -9924,6 +9937,88 @@ var JsonFileChannelStore = class {
|
|
|
9924
9937
|
writeFileSync(this.filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
9925
9938
|
}
|
|
9926
9939
|
};
|
|
9940
|
+
var ERC20_READ_ABI = [
|
|
9941
|
+
{ name: "balanceOf", type: "function", stateMutability: "view", inputs: [{ name: "account", type: "address" }], outputs: [{ type: "uint256" }] },
|
|
9942
|
+
{ name: "decimals", type: "function", stateMutability: "view", inputs: [], outputs: [{ type: "uint8" }] },
|
|
9943
|
+
{ name: "symbol", type: "function", stateMutability: "view", inputs: [], outputs: [{ type: "string" }] }
|
|
9944
|
+
];
|
|
9945
|
+
function parseEvmChainId(chainKey) {
|
|
9946
|
+
const parts = chainKey.split(":");
|
|
9947
|
+
const idStr = parts.length >= 3 ? parts[2] : parts[1];
|
|
9948
|
+
const id = Number.parseInt(idStr ?? "", 10);
|
|
9949
|
+
if (!Number.isFinite(id)) throw new Error(`Invalid EVM chain key "${chainKey}".`);
|
|
9950
|
+
return id;
|
|
9951
|
+
}
|
|
9952
|
+
async function readEvmTokenBalance(opts) {
|
|
9953
|
+
const chainId = parseEvmChainId(opts.chainKey);
|
|
9954
|
+
const client = createPublicClient2({
|
|
9955
|
+
transport: http2(opts.rpcUrl),
|
|
9956
|
+
chain: defineChain2({
|
|
9957
|
+
id: chainId,
|
|
9958
|
+
name: opts.chainKey,
|
|
9959
|
+
nativeCurrency: { name: "ETH", symbol: "ETH", decimals: 18 },
|
|
9960
|
+
rpcUrls: { default: { http: [opts.rpcUrl] } }
|
|
9961
|
+
})
|
|
9962
|
+
});
|
|
9963
|
+
const token = opts.tokenAddress;
|
|
9964
|
+
const owner = opts.owner;
|
|
9965
|
+
const [amount, decimals, symbol] = await Promise.all([
|
|
9966
|
+
client.readContract({ address: token, abi: ERC20_READ_ABI, functionName: "balanceOf", args: [owner] }),
|
|
9967
|
+
client.readContract({ address: token, abi: ERC20_READ_ABI, functionName: "decimals" }).catch(() => void 0),
|
|
9968
|
+
client.readContract({ address: token, abi: ERC20_READ_ABI, functionName: "symbol" }).catch(() => void 0)
|
|
9969
|
+
]);
|
|
9970
|
+
const out = { chain: "evm", address: opts.owner, amount: amount.toString() };
|
|
9971
|
+
if (typeof symbol === "string" && symbol) out.asset = symbol;
|
|
9972
|
+
if (decimals !== void 0) out.assetScale = Number(decimals);
|
|
9973
|
+
return out;
|
|
9974
|
+
}
|
|
9975
|
+
async function readSolanaTokenBalance(opts) {
|
|
9976
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
9977
|
+
const res = await fetchImpl(opts.rpcUrl, {
|
|
9978
|
+
method: "POST",
|
|
9979
|
+
headers: { "content-type": "application/json" },
|
|
9980
|
+
body: JSON.stringify({
|
|
9981
|
+
jsonrpc: "2.0",
|
|
9982
|
+
id: 1,
|
|
9983
|
+
method: "getTokenAccountsByOwner",
|
|
9984
|
+
params: [opts.owner, { mint: opts.mint }, { encoding: "jsonParsed", commitment: "confirmed" }]
|
|
9985
|
+
})
|
|
9986
|
+
});
|
|
9987
|
+
if (!res.ok) throw new Error(`Solana RPC request failed: HTTP ${res.status}`);
|
|
9988
|
+
const json = await res.json();
|
|
9989
|
+
if (json.error) throw new Error(`Solana RPC error: ${json.error.message ?? "unknown"}`);
|
|
9990
|
+
let amount = 0n;
|
|
9991
|
+
let decimals;
|
|
9992
|
+
for (const acc of json.result?.value ?? []) {
|
|
9993
|
+
const ta = acc.account?.data?.parsed?.info?.tokenAmount;
|
|
9994
|
+
if (ta?.amount) amount += BigInt(ta.amount);
|
|
9995
|
+
if (ta?.decimals !== void 0) decimals = ta.decimals;
|
|
9996
|
+
}
|
|
9997
|
+
const out = { chain: "solana", address: opts.owner, amount: amount.toString() };
|
|
9998
|
+
if (decimals !== void 0) out.assetScale = decimals;
|
|
9999
|
+
return out;
|
|
10000
|
+
}
|
|
10001
|
+
async function readMinaBalance(opts) {
|
|
10002
|
+
const fetchImpl = opts.fetchImpl ?? fetch;
|
|
10003
|
+
const query = "query($pk:String!){account(publicKey:$pk){balance{total}}}";
|
|
10004
|
+
const res = await fetchImpl(opts.graphqlUrl, {
|
|
10005
|
+
method: "POST",
|
|
10006
|
+
headers: { "content-type": "application/json" },
|
|
10007
|
+
body: JSON.stringify({ query, variables: { pk: opts.owner } })
|
|
10008
|
+
});
|
|
10009
|
+
if (!res.ok) throw new Error(`Mina GraphQL request failed: HTTP ${res.status}`);
|
|
10010
|
+
const json = await res.json();
|
|
10011
|
+
if (json.errors && json.errors.length > 0) {
|
|
10012
|
+
throw new Error(`Mina GraphQL error: ${json.errors[0]?.message ?? "unknown"}`);
|
|
10013
|
+
}
|
|
10014
|
+
return {
|
|
10015
|
+
chain: "mina",
|
|
10016
|
+
address: opts.owner,
|
|
10017
|
+
amount: String(json.data?.account?.balance?.total ?? "0"),
|
|
10018
|
+
asset: "MINA",
|
|
10019
|
+
assetScale: 9
|
|
10020
|
+
};
|
|
10021
|
+
}
|
|
9927
10022
|
var ARWEAVE_TX_ID_REGEX = /^[A-Za-z0-9_-]{43}$/;
|
|
9928
10023
|
async function requestBlobStorage(client, secretKey, params) {
|
|
9929
10024
|
const bid = params.bid ?? (params.ilpAmount !== void 0 ? String(params.ilpAmount) : void 0);
|
|
@@ -9992,8 +10087,8 @@ async function requestBlobStorage(client, secretKey, params) {
|
|
|
9992
10087
|
};
|
|
9993
10088
|
}
|
|
9994
10089
|
function extractArweaveTxId(base64Data) {
|
|
9995
|
-
const
|
|
9996
|
-
if (!
|
|
10090
|
+
const http3 = parseFulfillHttp(base64Data);
|
|
10091
|
+
if (!http3.isHttp) {
|
|
9997
10092
|
const legacy = decodeUtf8(fromBase64(base64Data));
|
|
9998
10093
|
if (!ARWEAVE_TX_ID_REGEX.test(legacy)) {
|
|
9999
10094
|
throw new Error(
|
|
@@ -10002,18 +10097,18 @@ function extractArweaveTxId(base64Data) {
|
|
|
10002
10097
|
}
|
|
10003
10098
|
return legacy;
|
|
10004
10099
|
}
|
|
10005
|
-
if (
|
|
10006
|
-
const detail =
|
|
10100
|
+
if (http3.status < 200 || http3.status >= 300) {
|
|
10101
|
+
const detail = http3.body ? ` - ${http3.body}` : "";
|
|
10007
10102
|
throw new Error(
|
|
10008
|
-
`Blob upload failed: DVM returned HTTP ${
|
|
10103
|
+
`Blob upload failed: DVM returned HTTP ${http3.status} ${http3.statusText}`.trimEnd() + detail
|
|
10009
10104
|
);
|
|
10010
10105
|
}
|
|
10011
10106
|
let parsed;
|
|
10012
10107
|
try {
|
|
10013
|
-
parsed = JSON.parse(
|
|
10108
|
+
parsed = JSON.parse(http3.body);
|
|
10014
10109
|
} catch {
|
|
10015
10110
|
throw new Error(
|
|
10016
|
-
`Blob upload response body was not valid JSON: "${
|
|
10111
|
+
`Blob upload response body was not valid JSON: "${http3.body}"`
|
|
10017
10112
|
);
|
|
10018
10113
|
}
|
|
10019
10114
|
const body = parsed;
|
|
@@ -10031,7 +10126,7 @@ function extractArweaveTxId(base64Data) {
|
|
|
10031
10126
|
}
|
|
10032
10127
|
}
|
|
10033
10128
|
throw new Error(
|
|
10034
|
-
`Blob upload response did not contain a valid Arweave tx ID: "${
|
|
10129
|
+
`Blob upload response did not contain a valid Arweave tx ID: "${http3.body}"`
|
|
10035
10130
|
);
|
|
10036
10131
|
}
|
|
10037
10132
|
var Http402Client = class {
|
|
@@ -10904,6 +10999,59 @@ var ToonClient = class {
|
|
|
10904
10999
|
if (!this.channelManager) throw new Error("ChannelManager not initialized");
|
|
10905
11000
|
return this.channelManager.getCumulativeAmount(channelId);
|
|
10906
11001
|
}
|
|
11002
|
+
/**
|
|
11003
|
+
* Gets the on-chain deposit total (locked collateral) for a tracked channel.
|
|
11004
|
+
* The available (spendable) balance is this minus the cumulative spent amount.
|
|
11005
|
+
*/
|
|
11006
|
+
getChannelDepositTotal(channelId) {
|
|
11007
|
+
if (!this.channelManager) throw new Error("ChannelManager not initialized");
|
|
11008
|
+
return this.channelManager.getDepositTotal(channelId);
|
|
11009
|
+
}
|
|
11010
|
+
/**
|
|
11011
|
+
* Read the on-chain settlement-token balance of this client's OWN wallet on
|
|
11012
|
+
* each configured chain (EVM token, Solana SPL, native MINA). A free read — no
|
|
11013
|
+
* signing, no payment. Best-effort per chain: a chain whose config is absent or
|
|
11014
|
+
* whose RPC read fails is omitted rather than failing the whole result, so the
|
|
11015
|
+
* wallet view degrades gracefully. Available after `start()` (Solana/Mina keys
|
|
11016
|
+
* are derived there).
|
|
11017
|
+
*/
|
|
11018
|
+
async getBalances() {
|
|
11019
|
+
const out = [];
|
|
11020
|
+
const evmAddress = this.getEvmAddress();
|
|
11021
|
+
const rpcUrls = this.config.chainRpcUrls;
|
|
11022
|
+
const tokens = this.config.preferredTokens;
|
|
11023
|
+
if (evmAddress && rpcUrls && tokens) {
|
|
11024
|
+
const chainKeys = this.config.supportedChains ?? Object.keys(rpcUrls);
|
|
11025
|
+
const chainKey = chainKeys.find((c) => c.startsWith("evm") && rpcUrls[c] && tokens[c]);
|
|
11026
|
+
const rpcUrl = chainKey ? rpcUrls[chainKey] : void 0;
|
|
11027
|
+
const tokenAddress = chainKey ? tokens[chainKey] : void 0;
|
|
11028
|
+
if (chainKey && rpcUrl && tokenAddress) {
|
|
11029
|
+
try {
|
|
11030
|
+
out.push(await readEvmTokenBalance({ rpcUrl, chainKey, tokenAddress, owner: evmAddress }));
|
|
11031
|
+
} catch {
|
|
11032
|
+
}
|
|
11033
|
+
}
|
|
11034
|
+
}
|
|
11035
|
+
const solAddress = this.getSolanaAddress();
|
|
11036
|
+
const sol = this.config.solanaChannel;
|
|
11037
|
+
if (solAddress && sol?.rpcUrl && sol.tokenMint) {
|
|
11038
|
+
try {
|
|
11039
|
+
out.push(
|
|
11040
|
+
await readSolanaTokenBalance({ rpcUrl: sol.rpcUrl, mint: sol.tokenMint, owner: solAddress })
|
|
11041
|
+
);
|
|
11042
|
+
} catch {
|
|
11043
|
+
}
|
|
11044
|
+
}
|
|
11045
|
+
const minaAddress = this.getMinaAddress();
|
|
11046
|
+
const mina = this.config.minaChannel;
|
|
11047
|
+
if (minaAddress && mina?.graphqlUrl) {
|
|
11048
|
+
try {
|
|
11049
|
+
out.push(await readMinaBalance({ graphqlUrl: mina.graphqlUrl, owner: minaAddress }));
|
|
11050
|
+
} catch {
|
|
11051
|
+
}
|
|
11052
|
+
}
|
|
11053
|
+
return out;
|
|
11054
|
+
}
|
|
10907
11055
|
/**
|
|
10908
11056
|
* Resolves an ILP destination address to a peer ID.
|
|
10909
11057
|
* Convention: destination "g.toon.peer1" → peerId "peer1" (last segment).
|
|
@@ -12027,6 +12175,9 @@ var ControlClient = class {
|
|
|
12027
12175
|
channels() {
|
|
12028
12176
|
return this.request("GET", "/channels");
|
|
12029
12177
|
}
|
|
12178
|
+
balances() {
|
|
12179
|
+
return this.request("GET", "/balances");
|
|
12180
|
+
}
|
|
12030
12181
|
swap(body) {
|
|
12031
12182
|
return this.request("POST", "/swap", body);
|
|
12032
12183
|
}
|
|
@@ -12232,4 +12383,4 @@ export {
|
|
|
12232
12383
|
@scure/bip32/lib/esm/index.js:
|
|
12233
12384
|
(*! scure-bip32 - MIT License (c) 2022 Patricio Palladino, Paul Miller (paulmillr.com) *)
|
|
12234
12385
|
*/
|
|
12235
|
-
//# sourceMappingURL=chunk-
|
|
12386
|
+
//# sourceMappingURL=chunk-ZVFLRFXS.js.map
|