@subly_fi/pay 0.4.0 → 0.4.1
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 +3 -3
- package/dist/deposit.js +4 -4
- package/dist/mcp-server.js +14 -14
- package/dist/pay.js +6 -6
- package/dist/withdraw.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,11 +26,11 @@ export SUBLY_DEMO_AGENT_KEYPAIR_PATH=~/.subly/agent.json
|
|
|
26
26
|
```
|
|
27
27
|
|
|
28
28
|
Send USDC (Solana mainnet) to the printed address — no SOL needed, fees are
|
|
29
|
-
sponsored — then deposit (vault minimum 1 USDC
|
|
30
|
-
wallet):
|
|
29
|
+
sponsored — then deposit (vault minimum is just over 1 USDC: share rounding
|
|
30
|
+
refuses exactly 1.000000; deposit self-registers the wallet):
|
|
31
31
|
|
|
32
32
|
```bash
|
|
33
|
-
npx -y @subly_fi/pay deposit
|
|
33
|
+
npx -y @subly_fi/pay deposit 1010000 # 1.01 USDC
|
|
34
34
|
```
|
|
35
35
|
|
|
36
36
|
## Use it
|
package/dist/deposit.js
CHANGED
|
@@ -993,7 +993,7 @@ var OnboardingError = class extends Error {
|
|
|
993
993
|
};
|
|
994
994
|
async function ensureWalletOnboarded(params) {
|
|
995
995
|
const fetchImpl = params.fetchImpl ?? fetch;
|
|
996
|
-
const baseUrl = params.
|
|
996
|
+
const baseUrl = params.relayerBaseUrl.replace(/\/$/, "");
|
|
997
997
|
const post = async (step, path, body) => {
|
|
998
998
|
const url = `${baseUrl}${path}`;
|
|
999
999
|
const serialized = JSON.stringify(body);
|
|
@@ -1095,7 +1095,7 @@ var VaultFlowClient = class {
|
|
|
1095
1095
|
pollTimeoutMs;
|
|
1096
1096
|
pollIntervalMs;
|
|
1097
1097
|
constructor(config) {
|
|
1098
|
-
this.baseUrl = config.
|
|
1098
|
+
this.baseUrl = config.relayerBaseUrl.replace(/\/$/, "");
|
|
1099
1099
|
this.signer = config.signer;
|
|
1100
1100
|
this.fetchImpl = config.fetchImpl ?? fetch;
|
|
1101
1101
|
this.lookupTablesFor = config.lookupTablesFor ?? ((serializedTransaction) => fetchLookupTablesForTransaction(config.rpc, serializedTransaction));
|
|
@@ -1353,14 +1353,14 @@ var rpc = createRpc(
|
|
|
1353
1353
|
process.env.SOLANA_RPC_URL ?? "https://api.mainnet-beta.solana.com"
|
|
1354
1354
|
);
|
|
1355
1355
|
var vaultFlows = new VaultFlowClient({
|
|
1356
|
-
|
|
1356
|
+
relayerBaseUrl,
|
|
1357
1357
|
signer,
|
|
1358
1358
|
rpc
|
|
1359
1359
|
});
|
|
1360
1360
|
console.log(`[deposit] agent wallet: ${signer.walletAddress}`);
|
|
1361
1361
|
console.log(`[deposit] relayer: ${relayerBaseUrl}`);
|
|
1362
1362
|
console.log("\n[deposit] step 0: ensure the wallet is registered (self-serve)");
|
|
1363
|
-
await ensureWalletOnboarded({
|
|
1363
|
+
await ensureWalletOnboarded({ relayerBaseUrl, signer });
|
|
1364
1364
|
console.log("[deposit] wallet registered and synced");
|
|
1365
1365
|
console.log(
|
|
1366
1366
|
`
|
package/dist/mcp-server.js
CHANGED
|
@@ -1006,7 +1006,7 @@ var OnboardingError = class extends Error {
|
|
|
1006
1006
|
};
|
|
1007
1007
|
async function ensureWalletOnboarded(params) {
|
|
1008
1008
|
const fetchImpl = params.fetchImpl ?? fetch;
|
|
1009
|
-
const baseUrl = params.
|
|
1009
|
+
const baseUrl = params.relayerBaseUrl.replace(/\/$/, "");
|
|
1010
1010
|
const post = async (step, path, body) => {
|
|
1011
1011
|
const url = `${baseUrl}${path}`;
|
|
1012
1012
|
const serialized = JSON.stringify(body);
|
|
@@ -1576,7 +1576,7 @@ var VaultFlowClient = class {
|
|
|
1576
1576
|
pollTimeoutMs;
|
|
1577
1577
|
pollIntervalMs;
|
|
1578
1578
|
constructor(config) {
|
|
1579
|
-
this.baseUrl = config.
|
|
1579
|
+
this.baseUrl = config.relayerBaseUrl.replace(/\/$/, "");
|
|
1580
1580
|
this.signer = config.signer;
|
|
1581
1581
|
this.fetchImpl = config.fetchImpl ?? fetch;
|
|
1582
1582
|
this.lookupTablesFor = config.lookupTablesFor ?? ((serializedTransaction) => fetchLookupTablesForTransaction(config.rpc, serializedTransaction));
|
|
@@ -1783,12 +1783,12 @@ var SERVER_INSTRUCTIONS = `Subly lets an agent pay for ANY standard x402 (HTTP 4
|
|
|
1783
1783
|
One-time setup: the operator needs a Solana keypair for the agent wallet. Subly does NOT create wallets; make one with \`solana-keygen new -o agent.json\` (or export a keypair from an existing wallet) and point SUBLY_DEMO_AGENT_KEYPAIR_PATH at it. The private key never leaves that file; this server only signs locally with it. Then fund the wallet with USDC on Solana mainnet \u2014 no SOL is ever needed, all vault transaction fees are sponsored.
|
|
1784
1784
|
|
|
1785
1785
|
From there the agent can do everything with these tools:
|
|
1786
|
-
1. deposit_to_subly_vault(amountRawUsdc) puts wallet USDC into the vault (minimum 1 USDC
|
|
1786
|
+
1. deposit_to_subly_vault(amountRawUsdc) puts wallet USDC into the vault (minimum just over 1 USDC, e.g. 1010000 raw) so it starts earning yield.
|
|
1787
1787
|
2. get_subly_yield_budget() shows the principal, position value, and the spendable yield a payment can use right now.
|
|
1788
1788
|
3. fetch_with_subly_payment(url) GETs or POSTs a paid resource from any x402 seller (e.g. Nansen): it realizes just enough yield to the agent's USDC ATA and pays the seller's standard x402 challenge, returning the body plus the payment details. If it returns insufficient_yield, that is expected \u2014 yield accrues over time; wait, do not loop.
|
|
1789
1789
|
4. withdraw_from_subly_vault(amountRawUsdc) exits: moves vault funds (principal included) back to the agent wallet's USDC account.`;
|
|
1790
1790
|
async function runMcpPaymentServer(config) {
|
|
1791
|
-
const { payer: payer2, signer: signer2,
|
|
1791
|
+
const { payer: payer2, signer: signer2, relayerBaseUrl: relayerBaseUrl2, defaultMaxAmountRawUsdc: defaultMaxAmountRawUsdc2 } = config;
|
|
1792
1792
|
const vaultFlows = config.vaultFlows ?? null;
|
|
1793
1793
|
const server = new Server(
|
|
1794
1794
|
{ name: "subly-payments", version: config.serverVersion ?? "0.3.0" },
|
|
@@ -1797,13 +1797,13 @@ async function runMcpPaymentServer(config) {
|
|
|
1797
1797
|
const vaultTools = vaultFlows === null ? [] : [
|
|
1798
1798
|
{
|
|
1799
1799
|
name: DEPOSIT_TOOL_NAME,
|
|
1800
|
-
description: "Deposit USDC from the agent wallet into the Subly/Kamino vault so it starts earning the yield that funds x402 payments. The transaction fee is sponsored \u2014 the agent wallet needs USDC only, never SOL. The vault minimum
|
|
1800
|
+
description: "Deposit USDC from the agent wallet into the Subly/Kamino vault so it starts earning the yield that funds x402 payments. The transaction fee is sponsored \u2014 the agent wallet needs USDC only, never SOL. The vault minimum is just over 1 USDC: share rounding refuses exactly 1000000 raw, so deposit e.g. 1010000 (1.01 USDC) or more. The deposited amount becomes protected principal: payments can only ever spend the yield on top of it.",
|
|
1801
1801
|
inputSchema: {
|
|
1802
1802
|
type: "object",
|
|
1803
1803
|
properties: {
|
|
1804
1804
|
amountRawUsdc: {
|
|
1805
1805
|
type: "string",
|
|
1806
|
-
description: 'Amount to deposit in raw USDC units (6 decimals, e.g. "
|
|
1806
|
+
description: 'Amount to deposit in raw USDC units (6 decimals, e.g. "1010000" = 1.01 USDC). Must exceed the 1 USDC vault minimum by a small rounding margin.'
|
|
1807
1807
|
}
|
|
1808
1808
|
},
|
|
1809
1809
|
required: ["amountRawUsdc"]
|
|
@@ -1958,7 +1958,7 @@ async function runMcpPaymentServer(config) {
|
|
|
1958
1958
|
];
|
|
1959
1959
|
if (vaultFlows !== null && vaultToolNames.includes(request.params.name)) {
|
|
1960
1960
|
try {
|
|
1961
|
-
await ensureWalletOnboarded({
|
|
1961
|
+
await ensureWalletOnboarded({ relayerBaseUrl: relayerBaseUrl2, signer: signer2 });
|
|
1962
1962
|
} catch {
|
|
1963
1963
|
}
|
|
1964
1964
|
if (request.params.name === BUDGET_TOOL_NAME) {
|
|
@@ -2098,7 +2098,7 @@ async function runMcpPaymentServer(config) {
|
|
|
2098
2098
|
}
|
|
2099
2099
|
});
|
|
2100
2100
|
try {
|
|
2101
|
-
await ensureWalletOnboarded({
|
|
2101
|
+
await ensureWalletOnboarded({ relayerBaseUrl: relayerBaseUrl2, signer: signer2 });
|
|
2102
2102
|
console.error("[subly-mcp] wallet registered and synced at the relayer");
|
|
2103
2103
|
} catch (error) {
|
|
2104
2104
|
console.error(
|
|
@@ -2108,7 +2108,7 @@ async function runMcpPaymentServer(config) {
|
|
|
2108
2108
|
const transport = new StdioServerTransport();
|
|
2109
2109
|
await server.connect(transport);
|
|
2110
2110
|
console.error(
|
|
2111
|
-
`[subly-mcp] ready: agent wallet ${signer2.walletAddress}, relayer ${
|
|
2111
|
+
`[subly-mcp] ready: agent wallet ${signer2.walletAddress}, relayer ${relayerBaseUrl2}, default cap ${formatRawUsdcAmount(defaultMaxAmountRawUsdc2)} USDC`
|
|
2112
2112
|
);
|
|
2113
2113
|
}
|
|
2114
2114
|
|
|
@@ -2128,7 +2128,7 @@ var RelayerYieldRealizer = class {
|
|
|
2128
2128
|
vaultFlows;
|
|
2129
2129
|
constructor(config) {
|
|
2130
2130
|
this.vaultFlows = new VaultFlowClient({
|
|
2131
|
-
|
|
2131
|
+
relayerBaseUrl: config.relayerBaseUrl,
|
|
2132
2132
|
signer: config.signer,
|
|
2133
2133
|
rpc: config.rpc,
|
|
2134
2134
|
...config.fetchImpl === void 0 ? {} : { fetchImpl: config.fetchImpl },
|
|
@@ -2225,7 +2225,7 @@ function errorCodeFrom(detail) {
|
|
|
2225
2225
|
// ../../src/client/relayer-payer.ts
|
|
2226
2226
|
function createRelayerX402Payer(config) {
|
|
2227
2227
|
const realizer = new RelayerYieldRealizer({
|
|
2228
|
-
|
|
2228
|
+
relayerBaseUrl: config.relayerBaseUrl,
|
|
2229
2229
|
signer: config.signer,
|
|
2230
2230
|
rpc: config.rpc
|
|
2231
2231
|
});
|
|
@@ -2388,7 +2388,7 @@ var agentSecretKey = loadSecretKeyBytes({
|
|
|
2388
2388
|
var signer = new LocalKeypairAgentWalletSigner(keyPairSigner);
|
|
2389
2389
|
var rpc = createRpc(rpcUrl);
|
|
2390
2390
|
var payer = createRelayerX402Payer({
|
|
2391
|
-
|
|
2391
|
+
relayerBaseUrl,
|
|
2392
2392
|
signer,
|
|
2393
2393
|
rpc,
|
|
2394
2394
|
x402Fetch: await createSvmX402Fetch({ agentSecretKey, rpcUrl }),
|
|
@@ -2398,10 +2398,10 @@ var payer = createRelayerX402Payer({
|
|
|
2398
2398
|
await runMcpPaymentServer({
|
|
2399
2399
|
payer,
|
|
2400
2400
|
signer,
|
|
2401
|
-
|
|
2401
|
+
relayerBaseUrl,
|
|
2402
2402
|
defaultMaxAmountRawUsdc,
|
|
2403
2403
|
vaultFlows: new VaultFlowClient({
|
|
2404
|
-
|
|
2404
|
+
relayerBaseUrl,
|
|
2405
2405
|
signer,
|
|
2406
2406
|
rpc
|
|
2407
2407
|
})
|
package/dist/pay.js
CHANGED
|
@@ -998,7 +998,7 @@ var OnboardingError = class extends Error {
|
|
|
998
998
|
};
|
|
999
999
|
async function ensureWalletOnboarded(params) {
|
|
1000
1000
|
const fetchImpl = params.fetchImpl ?? fetch;
|
|
1001
|
-
const baseUrl = params.
|
|
1001
|
+
const baseUrl = params.relayerBaseUrl.replace(/\/$/, "");
|
|
1002
1002
|
const post = async (step, path, body2) => {
|
|
1003
1003
|
const url2 = `${baseUrl}${path}`;
|
|
1004
1004
|
const serialized = JSON.stringify(body2);
|
|
@@ -1100,7 +1100,7 @@ var VaultFlowClient = class {
|
|
|
1100
1100
|
pollTimeoutMs;
|
|
1101
1101
|
pollIntervalMs;
|
|
1102
1102
|
constructor(config) {
|
|
1103
|
-
this.baseUrl = config.
|
|
1103
|
+
this.baseUrl = config.relayerBaseUrl.replace(/\/$/, "");
|
|
1104
1104
|
this.signer = config.signer;
|
|
1105
1105
|
this.fetchImpl = config.fetchImpl ?? fetch;
|
|
1106
1106
|
this.lookupTablesFor = config.lookupTablesFor ?? ((serializedTransaction) => fetchLookupTablesForTransaction(config.rpc, serializedTransaction));
|
|
@@ -1313,7 +1313,7 @@ var RelayerYieldRealizer = class {
|
|
|
1313
1313
|
vaultFlows;
|
|
1314
1314
|
constructor(config) {
|
|
1315
1315
|
this.vaultFlows = new VaultFlowClient({
|
|
1316
|
-
|
|
1316
|
+
relayerBaseUrl: config.relayerBaseUrl,
|
|
1317
1317
|
signer: config.signer,
|
|
1318
1318
|
rpc: config.rpc,
|
|
1319
1319
|
...config.fetchImpl === void 0 ? {} : { fetchImpl: config.fetchImpl },
|
|
@@ -1868,7 +1868,7 @@ function pendingPaymentKey(input) {
|
|
|
1868
1868
|
// ../../src/client/relayer-payer.ts
|
|
1869
1869
|
function createRelayerX402Payer(config) {
|
|
1870
1870
|
const realizer = new RelayerYieldRealizer({
|
|
1871
|
-
|
|
1871
|
+
relayerBaseUrl: config.relayerBaseUrl,
|
|
1872
1872
|
signer: config.signer,
|
|
1873
1873
|
rpc: config.rpc
|
|
1874
1874
|
});
|
|
@@ -2041,7 +2041,7 @@ var agentSecretKey = loadSecretKeyBytes({
|
|
|
2041
2041
|
var signer = new LocalKeypairAgentWalletSigner(keyPairSigner);
|
|
2042
2042
|
var rpc = createRpc(rpcUrl);
|
|
2043
2043
|
var payer = createRelayerX402Payer({
|
|
2044
|
-
|
|
2044
|
+
relayerBaseUrl,
|
|
2045
2045
|
signer,
|
|
2046
2046
|
rpc,
|
|
2047
2047
|
x402Fetch: await createSvmX402Fetch({ agentSecretKey, rpcUrl }),
|
|
@@ -2052,7 +2052,7 @@ var method = process.env.SUBLY_PAY_METHOD;
|
|
|
2052
2052
|
var body = process.env.SUBLY_PAY_BODY;
|
|
2053
2053
|
console.error(`[pay] agent ${signer.walletAddress} -> ${url}`);
|
|
2054
2054
|
try {
|
|
2055
|
-
await ensureWalletOnboarded({
|
|
2055
|
+
await ensureWalletOnboarded({ relayerBaseUrl, signer });
|
|
2056
2056
|
} catch (error) {
|
|
2057
2057
|
console.error(
|
|
2058
2058
|
`[pay] onboarding skipped: ${error instanceof Error ? error.message : String(error)}`
|
package/dist/withdraw.js
CHANGED
|
@@ -1038,7 +1038,7 @@ var VaultFlowClient = class {
|
|
|
1038
1038
|
pollTimeoutMs;
|
|
1039
1039
|
pollIntervalMs;
|
|
1040
1040
|
constructor(config) {
|
|
1041
|
-
this.baseUrl = config.
|
|
1041
|
+
this.baseUrl = config.relayerBaseUrl.replace(/\/$/, "");
|
|
1042
1042
|
this.signer = config.signer;
|
|
1043
1043
|
this.fetchImpl = config.fetchImpl ?? fetch;
|
|
1044
1044
|
this.lookupTablesFor = config.lookupTablesFor ?? ((serializedTransaction) => fetchLookupTablesForTransaction(config.rpc, serializedTransaction));
|
|
@@ -1296,7 +1296,7 @@ var rpc = createRpc(
|
|
|
1296
1296
|
process.env.SOLANA_RPC_URL ?? "https://api.mainnet-beta.solana.com"
|
|
1297
1297
|
);
|
|
1298
1298
|
var vaultFlows = new VaultFlowClient({
|
|
1299
|
-
|
|
1299
|
+
relayerBaseUrl,
|
|
1300
1300
|
signer,
|
|
1301
1301
|
rpc
|
|
1302
1302
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@subly_fi/pay",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.1",
|
|
4
4
|
"description": "Subly client: pay for ANY standard x402 (HTTP 402) paid API from Kamino vault yield — the seller needs no Subly integration. Ships an MCP server and a one-shot pay/deposit CLI; non-custodial (signs locally with your own key).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|