@obelyzk/sdk 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +370 -346
- package/bin/bitsage-demo.ts +0 -0
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +16 -6
- package/dist/index.mjs +17 -7
- package/dist/obelysk/index.d.mts +96 -7
- package/dist/obelysk/index.d.ts +96 -7
- package/dist/obelysk/index.js +325 -57
- package/dist/obelysk/index.mjs +313 -55
- package/dist/privacy/index.mjs +1 -1
- package/dist/react/index.mjs +1 -1
- package/package.json +5 -1
package/dist/obelysk/index.mjs
CHANGED
|
@@ -4,11 +4,12 @@ import {
|
|
|
4
4
|
GENERATOR_G,
|
|
5
5
|
GENERATOR_H,
|
|
6
6
|
ObelyskPrivacy,
|
|
7
|
+
__require,
|
|
7
8
|
ecAdd,
|
|
8
9
|
ecMul,
|
|
9
10
|
invMod,
|
|
10
11
|
randomScalar
|
|
11
|
-
} from "../chunk-
|
|
12
|
+
} from "../chunk-CGPFHXUF.mjs";
|
|
12
13
|
|
|
13
14
|
// src/obelysk/client.ts
|
|
14
15
|
import { RpcProvider } from "starknet";
|
|
@@ -1788,6 +1789,225 @@ var ShieldedSwapClient = class {
|
|
|
1788
1789
|
}
|
|
1789
1790
|
};
|
|
1790
1791
|
|
|
1792
|
+
// src/obelysk/ecies.ts
|
|
1793
|
+
var HKDF_INFO = "obelysk-ecies-v1";
|
|
1794
|
+
var ECIES_VERSION = 1;
|
|
1795
|
+
async function eciesEncrypt(payload, relayerPubkeyHex) {
|
|
1796
|
+
const subtle = getCrypto();
|
|
1797
|
+
const relayerPubkeyBytes = hexToBytes(relayerPubkeyHex);
|
|
1798
|
+
if (relayerPubkeyBytes.length !== 32) {
|
|
1799
|
+
throw new Error(`Invalid relayer public key length: ${relayerPubkeyBytes.length} (expected 32)`);
|
|
1800
|
+
}
|
|
1801
|
+
const relayerPubkey = await subtle.importKey(
|
|
1802
|
+
"raw",
|
|
1803
|
+
relayerPubkeyBytes.buffer,
|
|
1804
|
+
{ name: "X25519" },
|
|
1805
|
+
false,
|
|
1806
|
+
[]
|
|
1807
|
+
);
|
|
1808
|
+
const ephemeralKeyPair = await subtle.generateKey(
|
|
1809
|
+
{ name: "X25519" },
|
|
1810
|
+
true,
|
|
1811
|
+
["deriveBits"]
|
|
1812
|
+
);
|
|
1813
|
+
const sharedBits = await subtle.deriveBits(
|
|
1814
|
+
{ name: "X25519", public: relayerPubkey },
|
|
1815
|
+
ephemeralKeyPair.privateKey,
|
|
1816
|
+
256
|
|
1817
|
+
);
|
|
1818
|
+
const sharedKey = await subtle.importKey(
|
|
1819
|
+
"raw",
|
|
1820
|
+
sharedBits,
|
|
1821
|
+
{ name: "HKDF" },
|
|
1822
|
+
false,
|
|
1823
|
+
["deriveKey"]
|
|
1824
|
+
);
|
|
1825
|
+
const aesKey = await subtle.deriveKey(
|
|
1826
|
+
{
|
|
1827
|
+
name: "HKDF",
|
|
1828
|
+
hash: "SHA-256",
|
|
1829
|
+
salt: new ArrayBuffer(0),
|
|
1830
|
+
info: new TextEncoder().encode(HKDF_INFO)
|
|
1831
|
+
},
|
|
1832
|
+
sharedKey,
|
|
1833
|
+
{ name: "AES-GCM", length: 256 },
|
|
1834
|
+
false,
|
|
1835
|
+
["encrypt"]
|
|
1836
|
+
);
|
|
1837
|
+
const nonce = getRandomBytes(12);
|
|
1838
|
+
const plaintext = new TextEncoder().encode(JSON.stringify(payload));
|
|
1839
|
+
const ciphertext = await subtle.encrypt(
|
|
1840
|
+
{ name: "AES-GCM", iv: nonce },
|
|
1841
|
+
aesKey,
|
|
1842
|
+
plaintext
|
|
1843
|
+
);
|
|
1844
|
+
const ephPubRaw = await subtle.exportKey("raw", ephemeralKeyPair.publicKey);
|
|
1845
|
+
return {
|
|
1846
|
+
ephemeral_pubkey: bytesToHex(new Uint8Array(ephPubRaw)),
|
|
1847
|
+
ciphertext: bytesToBase64(new Uint8Array(ciphertext)),
|
|
1848
|
+
nonce: bytesToHex(nonce),
|
|
1849
|
+
version: ECIES_VERSION
|
|
1850
|
+
};
|
|
1851
|
+
}
|
|
1852
|
+
function getCrypto() {
|
|
1853
|
+
if (typeof globalThis.crypto?.subtle !== "undefined") {
|
|
1854
|
+
return globalThis.crypto.subtle;
|
|
1855
|
+
}
|
|
1856
|
+
try {
|
|
1857
|
+
const { webcrypto } = __require("crypto");
|
|
1858
|
+
return webcrypto.subtle;
|
|
1859
|
+
} catch {
|
|
1860
|
+
throw new Error("ECIES requires Web Crypto API (Node 20+ or a modern browser)");
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
function getRandomBytes(n) {
|
|
1864
|
+
if (typeof globalThis.crypto?.getRandomValues !== "undefined") {
|
|
1865
|
+
return globalThis.crypto.getRandomValues(new Uint8Array(n));
|
|
1866
|
+
}
|
|
1867
|
+
const { randomBytes } = __require("crypto");
|
|
1868
|
+
return new Uint8Array(randomBytes(n));
|
|
1869
|
+
}
|
|
1870
|
+
function hexToBytes(hex) {
|
|
1871
|
+
const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
1872
|
+
const bytes = new Uint8Array(clean.length / 2);
|
|
1873
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
1874
|
+
bytes[i] = parseInt(clean.slice(i * 2, i * 2 + 2), 16);
|
|
1875
|
+
}
|
|
1876
|
+
return bytes;
|
|
1877
|
+
}
|
|
1878
|
+
function bytesToHex(bytes) {
|
|
1879
|
+
return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1880
|
+
}
|
|
1881
|
+
function bytesToBase64(bytes) {
|
|
1882
|
+
if (typeof btoa === "function") {
|
|
1883
|
+
return btoa(String.fromCharCode(...bytes));
|
|
1884
|
+
}
|
|
1885
|
+
return Buffer.from(bytes).toString("base64");
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
// src/obelysk/denominations.ts
|
|
1889
|
+
var WBTC_DENOMINATIONS = [
|
|
1890
|
+
50000n,
|
|
1891
|
+
// 0.0005 BTC
|
|
1892
|
+
100000n,
|
|
1893
|
+
// 0.001 BTC
|
|
1894
|
+
500000n,
|
|
1895
|
+
// 0.005 BTC
|
|
1896
|
+
1000000n,
|
|
1897
|
+
// 0.01 BTC
|
|
1898
|
+
5000000n,
|
|
1899
|
+
// 0.05 BTC
|
|
1900
|
+
10000000n
|
|
1901
|
+
// 0.1 BTC
|
|
1902
|
+
];
|
|
1903
|
+
var SAGE_DENOMINATIONS = [
|
|
1904
|
+
10000000000000000n,
|
|
1905
|
+
// 0.01 SAGE
|
|
1906
|
+
50000000000000000n,
|
|
1907
|
+
// 0.05 SAGE
|
|
1908
|
+
100000000000000000n,
|
|
1909
|
+
// 0.1 SAGE
|
|
1910
|
+
500000000000000000n,
|
|
1911
|
+
// 0.5 SAGE
|
|
1912
|
+
1000000000000000000n,
|
|
1913
|
+
// 1 SAGE
|
|
1914
|
+
5000000000000000000n
|
|
1915
|
+
// 5 SAGE
|
|
1916
|
+
];
|
|
1917
|
+
var ETH_DENOMINATIONS = [
|
|
1918
|
+
1000000000000000n,
|
|
1919
|
+
// 0.001 ETH
|
|
1920
|
+
5000000000000000n,
|
|
1921
|
+
// 0.005 ETH
|
|
1922
|
+
10000000000000000n,
|
|
1923
|
+
// 0.01 ETH
|
|
1924
|
+
50000000000000000n,
|
|
1925
|
+
// 0.05 ETH
|
|
1926
|
+
100000000000000000n,
|
|
1927
|
+
// 0.1 ETH
|
|
1928
|
+
500000000000000000n
|
|
1929
|
+
// 0.5 ETH
|
|
1930
|
+
];
|
|
1931
|
+
var STRK_DENOMINATIONS = [
|
|
1932
|
+
50000000000000000n,
|
|
1933
|
+
// 0.05 STRK
|
|
1934
|
+
100000000000000000n,
|
|
1935
|
+
// 0.1 STRK
|
|
1936
|
+
500000000000000000n,
|
|
1937
|
+
// 0.5 STRK
|
|
1938
|
+
1000000000000000000n,
|
|
1939
|
+
// 1 STRK
|
|
1940
|
+
5000000000000000000n
|
|
1941
|
+
// 5 STRK
|
|
1942
|
+
];
|
|
1943
|
+
var USDC_DENOMINATIONS = [
|
|
1944
|
+
1000000n,
|
|
1945
|
+
// 1 USDC
|
|
1946
|
+
5000000n,
|
|
1947
|
+
// 5 USDC
|
|
1948
|
+
10000000n,
|
|
1949
|
+
// 10 USDC
|
|
1950
|
+
50000000n,
|
|
1951
|
+
// 50 USDC
|
|
1952
|
+
100000000n,
|
|
1953
|
+
// 100 USDC
|
|
1954
|
+
500000000n
|
|
1955
|
+
// 500 USDC
|
|
1956
|
+
];
|
|
1957
|
+
var VM31_DENOMINATIONS = {
|
|
1958
|
+
0: WBTC_DENOMINATIONS,
|
|
1959
|
+
1: SAGE_DENOMINATIONS,
|
|
1960
|
+
2: ETH_DENOMINATIONS,
|
|
1961
|
+
3: STRK_DENOMINATIONS,
|
|
1962
|
+
4: USDC_DENOMINATIONS
|
|
1963
|
+
};
|
|
1964
|
+
var DENOMINATION_BY_SYMBOL = {
|
|
1965
|
+
wbtc: WBTC_DENOMINATIONS,
|
|
1966
|
+
sage: SAGE_DENOMINATIONS,
|
|
1967
|
+
eth: ETH_DENOMINATIONS,
|
|
1968
|
+
strk: STRK_DENOMINATIONS,
|
|
1969
|
+
usdc: USDC_DENOMINATIONS
|
|
1970
|
+
};
|
|
1971
|
+
function validateDenomination(amount, assetIdOrSymbol) {
|
|
1972
|
+
let denoms;
|
|
1973
|
+
if (typeof assetIdOrSymbol === "number") {
|
|
1974
|
+
denoms = VM31_DENOMINATIONS[assetIdOrSymbol];
|
|
1975
|
+
} else {
|
|
1976
|
+
denoms = DENOMINATION_BY_SYMBOL[assetIdOrSymbol.toLowerCase()];
|
|
1977
|
+
}
|
|
1978
|
+
if (!denoms) return;
|
|
1979
|
+
if (!denoms.includes(amount)) {
|
|
1980
|
+
throw new Error(
|
|
1981
|
+
`Deposit must use a standard denomination for asset ${assetIdOrSymbol}. Got ${amount}. Valid: [${denoms.join(", ")}]`
|
|
1982
|
+
);
|
|
1983
|
+
}
|
|
1984
|
+
}
|
|
1985
|
+
function splitIntoDenominations(amount, assetIdOrSymbol) {
|
|
1986
|
+
let denoms;
|
|
1987
|
+
if (typeof assetIdOrSymbol === "number") {
|
|
1988
|
+
denoms = VM31_DENOMINATIONS[assetIdOrSymbol];
|
|
1989
|
+
} else {
|
|
1990
|
+
denoms = DENOMINATION_BY_SYMBOL[assetIdOrSymbol.toLowerCase()];
|
|
1991
|
+
}
|
|
1992
|
+
if (!denoms) return { denominations: [amount], remainder: 0n };
|
|
1993
|
+
const sorted = [...denoms].sort((a, b) => b > a ? 1 : b < a ? -1 : 0);
|
|
1994
|
+
const result = [];
|
|
1995
|
+
let remaining = amount;
|
|
1996
|
+
for (const denom of sorted) {
|
|
1997
|
+
while (remaining >= denom) {
|
|
1998
|
+
result.push(denom);
|
|
1999
|
+
remaining -= denom;
|
|
2000
|
+
}
|
|
2001
|
+
}
|
|
2002
|
+
return { denominations: result, remainder: remaining };
|
|
2003
|
+
}
|
|
2004
|
+
function getDenominations(assetIdOrSymbol) {
|
|
2005
|
+
if (typeof assetIdOrSymbol === "number") {
|
|
2006
|
+
return VM31_DENOMINATIONS[assetIdOrSymbol];
|
|
2007
|
+
}
|
|
2008
|
+
return DENOMINATION_BY_SYMBOL[assetIdOrSymbol.toLowerCase()];
|
|
2009
|
+
}
|
|
2010
|
+
|
|
1791
2011
|
// src/obelysk/vm31Vault.ts
|
|
1792
2012
|
var VM31VaultClient = class {
|
|
1793
2013
|
constructor(obelysk) {
|
|
@@ -1802,6 +2022,8 @@ var VM31VaultClient = class {
|
|
|
1802
2022
|
get relayerApiKey() {
|
|
1803
2023
|
return this.obelysk.relayerApiKey;
|
|
1804
2024
|
}
|
|
2025
|
+
/** Cached relayer X25519 public key (fetched on first encrypted submit) */
|
|
2026
|
+
_relayerPubkey = null;
|
|
1805
2027
|
async relayerFetch(path, init) {
|
|
1806
2028
|
const url = `${this.relayerUrl}${path}`;
|
|
1807
2029
|
const headers = { "Content-Type": "application/json" };
|
|
@@ -1813,6 +2035,27 @@ var VM31VaultClient = class {
|
|
|
1813
2035
|
}
|
|
1814
2036
|
return res.json();
|
|
1815
2037
|
}
|
|
2038
|
+
/**
|
|
2039
|
+
* Submit a payload to the relayer, encrypted with ECIES.
|
|
2040
|
+
* Falls back to plaintext if `encrypt: false` is passed.
|
|
2041
|
+
*/
|
|
2042
|
+
async relayerSubmit(payload, encrypt = true) {
|
|
2043
|
+
if (!encrypt) {
|
|
2044
|
+
return this.relayerFetch("/submit", {
|
|
2045
|
+
method: "POST",
|
|
2046
|
+
body: JSON.stringify(payload)
|
|
2047
|
+
});
|
|
2048
|
+
}
|
|
2049
|
+
if (!this._relayerPubkey) {
|
|
2050
|
+
const keyInfo = await this.getRelayerPublicKey();
|
|
2051
|
+
this._relayerPubkey = keyInfo.publicKey;
|
|
2052
|
+
}
|
|
2053
|
+
const envelope = await eciesEncrypt(payload, this._relayerPubkey);
|
|
2054
|
+
return this.relayerFetch("/submit", {
|
|
2055
|
+
method: "POST",
|
|
2056
|
+
body: JSON.stringify(envelope)
|
|
2057
|
+
});
|
|
2058
|
+
}
|
|
1816
2059
|
// --------------------------------------------------------------------------
|
|
1817
2060
|
// On-chain reads (callContract to vm31_pool)
|
|
1818
2061
|
// --------------------------------------------------------------------------
|
|
@@ -1976,61 +2219,65 @@ var VM31VaultClient = class {
|
|
|
1976
2219
|
algorithm: data.algorithm
|
|
1977
2220
|
};
|
|
1978
2221
|
}
|
|
1979
|
-
/**
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
2222
|
+
/**
|
|
2223
|
+
* Submit a deposit transaction to the relayer.
|
|
2224
|
+
* Validates denomination (privacy gap #7) and encrypts with ECIES by default.
|
|
2225
|
+
* @param encrypt - Set to false for legacy plaintext mode (default: true)
|
|
2226
|
+
*/
|
|
2227
|
+
async submitDeposit(params, encrypt = true) {
|
|
2228
|
+
validateDenomination(params.amount, params.assetId);
|
|
2229
|
+
return this.relayerSubmit({
|
|
2230
|
+
type: "deposit",
|
|
2231
|
+
amount: Number(params.amount),
|
|
2232
|
+
asset_id: params.assetId,
|
|
2233
|
+
recipient_pubkey: params.recipientPubkey,
|
|
2234
|
+
recipient_viewing_key: params.recipientViewingKey
|
|
2235
|
+
}, encrypt);
|
|
1991
2236
|
}
|
|
1992
|
-
/**
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2237
|
+
/**
|
|
2238
|
+
* Submit a withdrawal transaction to the relayer.
|
|
2239
|
+
* Withdrawals are not denomination-restricted.
|
|
2240
|
+
* @param encrypt - Set to false for legacy plaintext mode (default: true)
|
|
2241
|
+
*/
|
|
2242
|
+
async submitWithdraw(params, encrypt = true) {
|
|
2243
|
+
return this.relayerSubmit({
|
|
2244
|
+
type: "withdraw",
|
|
2245
|
+
amount: Number(params.amount),
|
|
2246
|
+
asset_id: params.assetId,
|
|
2247
|
+
note: {
|
|
2248
|
+
owner_pubkey: params.note.owner_pubkey,
|
|
2249
|
+
asset_id: params.note.asset_id,
|
|
2250
|
+
amount_lo: params.note.amount_lo,
|
|
2251
|
+
amount_hi: params.note.amount_hi,
|
|
2252
|
+
blinding: params.note.blinding
|
|
2253
|
+
},
|
|
2254
|
+
spending_key: params.spendingKey,
|
|
2255
|
+
merkle_path: params.merklePath,
|
|
2256
|
+
merkle_root: params.merkleRoot,
|
|
2257
|
+
withdrawal_binding: params.withdrawalBinding,
|
|
2258
|
+
binding_salt: params.bindingSalt
|
|
2259
|
+
}, encrypt);
|
|
2014
2260
|
}
|
|
2015
|
-
/**
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
})
|
|
2033
|
-
|
|
2261
|
+
/**
|
|
2262
|
+
* Submit a private transfer transaction to the relayer.
|
|
2263
|
+
* Transfers are not denomination-restricted.
|
|
2264
|
+
* @param encrypt - Set to false for legacy plaintext mode (default: true)
|
|
2265
|
+
*/
|
|
2266
|
+
async submitTransfer(params, encrypt = true) {
|
|
2267
|
+
return this.relayerSubmit({
|
|
2268
|
+
type: "transfer",
|
|
2269
|
+
amount: Number(params.amount),
|
|
2270
|
+
asset_id: params.assetId,
|
|
2271
|
+
recipient_pubkey: params.recipientPubkey,
|
|
2272
|
+
recipient_viewing_key: params.recipientViewingKey,
|
|
2273
|
+
sender_viewing_key: params.senderViewingKey,
|
|
2274
|
+
input_notes: params.inputNotes.map((n) => ({
|
|
2275
|
+
note: n.note,
|
|
2276
|
+
spending_key: n.spendingKey,
|
|
2277
|
+
merkle_path: n.merklePath
|
|
2278
|
+
})),
|
|
2279
|
+
merkle_root: params.merkleRoot
|
|
2280
|
+
}, encrypt);
|
|
2034
2281
|
}
|
|
2035
2282
|
/** Query batch info from the relayer */
|
|
2036
2283
|
async queryBatch(batchId) {
|
|
@@ -2747,7 +2994,9 @@ export {
|
|
|
2747
2994
|
CURVE_ORDER,
|
|
2748
2995
|
ConfidentialTransferClient,
|
|
2749
2996
|
DARKPOOL_ASSET_IDS,
|
|
2997
|
+
DENOMINATION_BY_SYMBOL,
|
|
2750
2998
|
DarkPoolClient,
|
|
2999
|
+
ETH_DENOMINATIONS,
|
|
2751
3000
|
FIELD_PRIME,
|
|
2752
3001
|
GENERATOR_G,
|
|
2753
3002
|
GENERATOR_H,
|
|
@@ -2762,25 +3011,34 @@ export {
|
|
|
2762
3011
|
PrivacyPoolClient,
|
|
2763
3012
|
PrivacyRouterClient,
|
|
2764
3013
|
ProverStakingClient,
|
|
3014
|
+
SAGE_DENOMINATIONS,
|
|
3015
|
+
STRK_DENOMINATIONS,
|
|
2765
3016
|
ShieldedSwapClient,
|
|
2766
3017
|
StealthClient,
|
|
2767
3018
|
TOKEN_DECIMALS,
|
|
3019
|
+
USDC_DENOMINATIONS,
|
|
2768
3020
|
VM31BridgeClient,
|
|
2769
3021
|
VM31VaultClient,
|
|
2770
3022
|
VM31_ASSET_IDS,
|
|
3023
|
+
VM31_DENOMINATIONS,
|
|
3024
|
+
WBTC_DENOMINATIONS,
|
|
2771
3025
|
commitmentToHash,
|
|
2772
3026
|
createAEHint,
|
|
2773
3027
|
createEncryptionProof,
|
|
2774
3028
|
deriveNullifier,
|
|
2775
3029
|
ecAdd2 as ecAdd,
|
|
2776
3030
|
ecMul2 as ecMul,
|
|
3031
|
+
eciesEncrypt,
|
|
2777
3032
|
elgamalEncrypt,
|
|
2778
3033
|
formatAmount,
|
|
2779
3034
|
getContracts,
|
|
3035
|
+
getDenominations,
|
|
2780
3036
|
getRpcUrl,
|
|
2781
3037
|
mod,
|
|
2782
3038
|
modInverse,
|
|
2783
3039
|
parseAmount,
|
|
2784
3040
|
pedersenCommit,
|
|
2785
|
-
randomScalar2 as randomScalar
|
|
3041
|
+
randomScalar2 as randomScalar,
|
|
3042
|
+
splitIntoDenominations,
|
|
3043
|
+
validateDenomination
|
|
2786
3044
|
};
|
package/dist/privacy/index.mjs
CHANGED
package/dist/react/index.mjs
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@obelyzk/sdk",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"description": "BitSage Network SDK - Client library for distributed compute, privacy swaps, and Obelysk encryption",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -97,5 +97,9 @@
|
|
|
97
97
|
"homepage": "https://bitsage.network",
|
|
98
98
|
"bugs": {
|
|
99
99
|
"url": "https://github.com/Bitsage-Network/bitsage-network/issues"
|
|
100
|
+
},
|
|
101
|
+
"optionalDependencies": {
|
|
102
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
103
|
+
"zod": "^4.3.6"
|
|
100
104
|
}
|
|
101
105
|
}
|