@hsuite/smart-engines-cli 1.1.0 → 1.2.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/dist/__tests__/helpers/fixtures.d.ts +48 -0
- package/dist/__tests__/helpers/fixtures.d.ts.map +1 -0
- package/dist/__tests__/helpers/fixtures.js +79 -0
- package/dist/__tests__/helpers/fixtures.js.map +1 -0
- package/dist/_lib/cluster.d.ts +15 -0
- package/dist/_lib/cluster.d.ts.map +1 -0
- package/dist/_lib/cluster.js +18 -0
- package/dist/_lib/cluster.js.map +1 -0
- package/dist/_lib/subscription-client.d.ts +152 -0
- package/dist/_lib/subscription-client.d.ts.map +1 -0
- package/dist/_lib/subscription-client.js +84 -0
- package/dist/_lib/subscription-client.js.map +1 -0
- package/dist/_lib/subscription-env.d.ts +20 -0
- package/dist/_lib/subscription-env.d.ts.map +1 -0
- package/dist/_lib/subscription-env.js +28 -0
- package/dist/_lib/subscription-env.js.map +1 -0
- package/dist/commands/billing.d.ts +17 -0
- package/dist/commands/billing.d.ts.map +1 -0
- package/dist/commands/billing.js +59 -0
- package/dist/commands/billing.js.map +1 -0
- package/dist/commands/deploy.d.ts.map +1 -1
- package/dist/commands/deploy.js +32 -10
- package/dist/commands/deploy.js.map +1 -1
- package/dist/commands/downgrade.d.ts +22 -0
- package/dist/commands/downgrade.d.ts.map +1 -0
- package/dist/commands/downgrade.js +55 -0
- package/dist/commands/downgrade.js.map +1 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +5 -7
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/renew.d.ts +19 -0
- package/dist/commands/renew.d.ts.map +1 -0
- package/dist/commands/renew.js +58 -0
- package/dist/commands/renew.js.map +1 -0
- package/dist/commands/subscribe.d.ts +40 -4
- package/dist/commands/subscribe.d.ts.map +1 -1
- package/dist/commands/subscribe.js +156 -75
- package/dist/commands/subscribe.js.map +1 -1
- package/dist/commands/upgrade.d.ts +41 -0
- package/dist/commands/upgrade.d.ts.map +1 -0
- package/dist/commands/upgrade.js +128 -0
- package/dist/commands/upgrade.js.map +1 -0
- package/dist/commands/usage.d.ts +22 -0
- package/dist/commands/usage.d.ts.map +1 -0
- package/dist/commands/usage.js +81 -0
- package/dist/commands/usage.js.map +1 -0
- package/dist/commands/verify.d.ts +56 -0
- package/dist/commands/verify.d.ts.map +1 -0
- package/dist/commands/verify.js +291 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -2
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
|
@@ -4,106 +4,187 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.subscribeCommand = void 0;
|
|
7
|
+
exports.runSubscribe = runSubscribe;
|
|
7
8
|
/**
|
|
8
|
-
* `hsuite subscribe` —
|
|
9
|
+
* `hsuite subscribe` — Mint a subscription NFT against the validator's
|
|
10
|
+
* `/api/v3/subscription/*` surface.
|
|
9
11
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
12
|
+
* Flow (per docs/superpowers/specs/2026-05-27-developer-subscription-gating.md §3.5):
|
|
13
|
+
* 1. Read XRPL_ADDRESS + XRPL_SEED from env (written by `hsuite init`).
|
|
14
|
+
* 2. POST /api/v3/subscription/request → server creates subscription doc.
|
|
15
|
+
* - `free_testnet`: server auto-activates + mints. CLI polls /status
|
|
16
|
+
* until NFT serial is set.
|
|
17
|
+
* - paid tier: server returns depositInstructions. CLI displays them,
|
|
18
|
+
* polls /status every 5s until status: 'PENDING_MINT' (deposit
|
|
19
|
+
* confirmed), then POSTs /mint to flip ACTIVE.
|
|
20
|
+
* 3. Verify NFT serial lands on the wallet via GET /status.
|
|
21
|
+
* 4. Write SUBSCRIPTION_APP_ID + SUBSCRIPTION_NFT_SERIAL to .env.
|
|
13
22
|
*/
|
|
14
23
|
const commander_1 = require("commander");
|
|
15
24
|
const chalk_1 = __importDefault(require("chalk"));
|
|
16
25
|
const ora_1 = __importDefault(require("ora"));
|
|
17
|
-
const
|
|
26
|
+
const crypto_1 = require("crypto");
|
|
18
27
|
const env_1 = require("../_lib/env");
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
process.exit(1);
|
|
28
|
+
const subscription_client_1 = require("../_lib/subscription-client");
|
|
29
|
+
const subscription_env_1 = require("../_lib/subscription-env");
|
|
30
|
+
const VALID_TIERS = ['free_testnet', 'starter', 'professional', 'enterprise'];
|
|
31
|
+
const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
32
|
+
/**
|
|
33
|
+
* Pure orchestration body — exported for unit tests.
|
|
34
|
+
*
|
|
35
|
+
* Returns the appId + NFT serial (when minted) so callers can persist them.
|
|
36
|
+
* Throws on every error path; the command-level action wraps this and
|
|
37
|
+
* exits the process.
|
|
38
|
+
*/
|
|
39
|
+
async function runSubscribe(opts) {
|
|
40
|
+
const env = (0, env_1.readEnv)(opts.env);
|
|
41
|
+
const { address } = (0, subscription_env_1.requireXrplCreds)(env);
|
|
42
|
+
const tier = opts.tier;
|
|
43
|
+
if (!VALID_TIERS.includes(tier)) {
|
|
44
|
+
throw new Error(`unknown tier "${opts.tier}". Valid: ${VALID_TIERS.join(', ')}`);
|
|
37
45
|
}
|
|
38
|
-
|
|
39
|
-
// hyphens, max 63 chars). Normalise the display-name accordingly so a
|
|
40
|
-
// CLI invocation with a free-text APP_NAME doesn't 400 at the boundary.
|
|
41
|
-
const rawAppName = opts.name ?? env.get('APP_NAME') ?? 'smart-app-showcase';
|
|
42
|
-
const appName = rawAppName
|
|
43
|
-
.toLowerCase()
|
|
44
|
-
.replace(/[^a-z0-9-]+/g, '-')
|
|
45
|
-
.replace(/^-+|-+$/g, '')
|
|
46
|
-
.slice(0, 63) || 'smart-app-showcase';
|
|
47
|
-
const services = opts.services
|
|
46
|
+
const selectedNetworks = opts.networks
|
|
48
47
|
.split(',')
|
|
49
48
|
.map((s) => s.trim())
|
|
50
49
|
.filter(Boolean);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
try {
|
|
54
|
-
signer = (0, env_1.buildSignerFromEnv)(env);
|
|
55
|
-
}
|
|
56
|
-
catch (err) {
|
|
57
|
-
spinner.fail(err.message);
|
|
58
|
-
process.exit(1);
|
|
50
|
+
if (selectedNetworks.length === 0) {
|
|
51
|
+
throw new Error('At least one network required (e.g. --networks xrpl)');
|
|
59
52
|
}
|
|
60
|
-
|
|
61
|
-
const client = new
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
53
|
+
const baseUrl = (0, subscription_env_1.requireValidatorUrl)(env, { gateway: opts.gateway });
|
|
54
|
+
const client = (opts.clientFactory ?? ((b) => new subscription_client_1.SubscriptionClient({ baseUrl: b })))(baseUrl);
|
|
55
|
+
const sleep = opts.sleep ?? defaultSleep;
|
|
56
|
+
const appId = opts.appId ??
|
|
57
|
+
env.get('SUBSCRIPTION_APP_ID') ??
|
|
58
|
+
`app-${(0, crypto_1.randomUUID)().slice(0, 8)}`;
|
|
59
|
+
const appName = opts.appName ?? env.get('APP_NAME') ?? 'Smart App Showcase';
|
|
60
|
+
// Step 1: POST /request
|
|
61
|
+
let requestResp;
|
|
68
62
|
try {
|
|
69
|
-
await client.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
63
|
+
requestResp = await client.request({
|
|
64
|
+
appId,
|
|
65
|
+
developerAccountId: address,
|
|
66
|
+
chain: 'xrpl',
|
|
67
|
+
appName,
|
|
68
|
+
selectedTier: tier,
|
|
69
|
+
selectedNetworks,
|
|
74
70
|
});
|
|
75
71
|
}
|
|
76
72
|
catch (err) {
|
|
77
|
-
|
|
78
|
-
|
|
73
|
+
throw new Error(`subscription request failed: ${err.message}`);
|
|
74
|
+
}
|
|
75
|
+
if (!requestResp.success) {
|
|
76
|
+
throw new Error(`subscription request rejected: ${requestResp.message ?? 'unknown error'}`);
|
|
79
77
|
}
|
|
80
|
-
|
|
81
|
-
|
|
78
|
+
const status = await (async () => {
|
|
79
|
+
// Step 2a: free_testnet path — server auto-activates. Poll until NFT serial set.
|
|
80
|
+
if (tier === 'free_testnet') {
|
|
81
|
+
return pollStatus(client, appId, sleep, opts, (s) => Boolean(s.subscriptionNftSerial));
|
|
82
|
+
}
|
|
83
|
+
// Step 2b: paid tier — display deposit instructions + poll until PENDING_MINT.
|
|
84
|
+
if (!requestResp.depositInstructions) {
|
|
85
|
+
throw new Error('paid tier returned no depositInstructions — server contract violation');
|
|
86
|
+
}
|
|
87
|
+
renderDepositInstructions(requestResp.depositInstructions, tier);
|
|
88
|
+
await pollStatus(client, appId, sleep, opts, (s) => isPendingMint(s.status));
|
|
89
|
+
// Step 3: POST /mint
|
|
90
|
+
const mintResp = await client.mint(appId);
|
|
91
|
+
if (!mintResp.success) {
|
|
92
|
+
throw new Error('mint failed (server returned success=false)');
|
|
93
|
+
}
|
|
94
|
+
// Step 4: poll until NFT serial is set.
|
|
95
|
+
return pollStatus(client, appId, sleep, opts, (s) => Boolean(s.subscriptionNftSerial));
|
|
96
|
+
})();
|
|
97
|
+
return {
|
|
98
|
+
appId,
|
|
99
|
+
subscriptionId: status.subscriptionId,
|
|
100
|
+
nftSerial: status.subscriptionNftSerial,
|
|
101
|
+
tier,
|
|
102
|
+
status: status.status,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function isPendingMint(status) {
|
|
106
|
+
if (!status)
|
|
107
|
+
return false;
|
|
108
|
+
// SubscriptionStatus enum values from libs/multi-chain-core. Accept both
|
|
109
|
+
// canonical `pending_mint` and an already-active state (server may skip
|
|
110
|
+
// straight to ACTIVE if it's already minted by the time we poll).
|
|
111
|
+
const s = status.toLowerCase();
|
|
112
|
+
return s === 'pending_mint' || s === 'active' || s === 'minting';
|
|
113
|
+
}
|
|
114
|
+
async function pollStatus(client, appId, sleep, opts, done) {
|
|
115
|
+
const interval = opts.pollIntervalMs ?? 5000;
|
|
116
|
+
const timeout = opts.pollTimeoutMs ?? 5 * 60 * 1000;
|
|
117
|
+
const deadline = Date.now() + timeout;
|
|
118
|
+
// First tick immediately so tests that prime a single response don't have
|
|
119
|
+
// to wait the full 5s.
|
|
120
|
+
while (true) {
|
|
121
|
+
const status = await client.status(appId);
|
|
122
|
+
if (done(status))
|
|
123
|
+
return status;
|
|
124
|
+
if (Date.now() > deadline) {
|
|
125
|
+
throw new Error(`timed out waiting for subscription status for ${appId} after ${timeout}ms`);
|
|
126
|
+
}
|
|
127
|
+
await sleep(interval);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function renderDepositInstructions(d, tier) {
|
|
131
|
+
const xummDeeplink = buildXummDeeplink(d);
|
|
132
|
+
console.log(chalk_1.default.bold.yellow('\n Deposit required to mint your subscription NFT:'));
|
|
133
|
+
console.log(chalk_1.default.gray(` tier: ${tier}`));
|
|
134
|
+
console.log(chalk_1.default.gray(` chain: ${d.chain}`));
|
|
135
|
+
console.log(chalk_1.default.gray(` amount: ${d.amount} (token ${d.tokenId})`));
|
|
136
|
+
console.log(chalk_1.default.gray(` to: ${d.walletAddress}\n`));
|
|
137
|
+
console.log(chalk_1.default.cyan(` XUMM deeplink:`));
|
|
138
|
+
console.log(chalk_1.default.cyan(` ${xummDeeplink}\n`));
|
|
139
|
+
console.log(chalk_1.default.gray(' Waiting for deposit confirmation...\n'));
|
|
140
|
+
}
|
|
141
|
+
function buildXummDeeplink(d) {
|
|
142
|
+
if (d.chain !== 'xrpl') {
|
|
143
|
+
return `(no deeplink: chain=${d.chain})`;
|
|
144
|
+
}
|
|
145
|
+
// Minimal Xumm deeplink shape; full IssuedCurrency requires JSON payload
|
|
146
|
+
// pushed through https://xumm.app/sign — for the CLI we surface the raw
|
|
147
|
+
// tx params so the user can paste them into their wallet.
|
|
148
|
+
return `xumm://xrpl/send?to=${encodeURIComponent(d.walletAddress)}&amount=${encodeURIComponent(d.amount)}&token=${encodeURIComponent(d.tokenId)}`;
|
|
149
|
+
}
|
|
150
|
+
exports.subscribeCommand = new commander_1.Command('subscribe')
|
|
151
|
+
.description('Mint a subscription NFT against the cluster')
|
|
152
|
+
.option('--env <file>', 'Env file with XRPL creds', '.env.local')
|
|
153
|
+
.option('--gateway <url>', 'Validator/gateway URL (defaults to VALIDATOR_URL in env)')
|
|
154
|
+
.option('--tier <tier>', 'Subscription tier (free_testnet|starter|professional|enterprise)', 'free_testnet')
|
|
155
|
+
.option('--networks <list>', 'Comma-separated networks (hedera,xrpl,etc.)', 'xrpl')
|
|
156
|
+
.option('--app-name <name>', 'Smart-app display name')
|
|
157
|
+
.option('--app-id <id>', 'Reuse an existing app id (default: generate uuid)')
|
|
158
|
+
.action(async (opts) => {
|
|
159
|
+
console.log(chalk_1.default.bold.cyan('\n hsuite subscribe\n'));
|
|
160
|
+
console.log(chalk_1.default.gray(` env: ${opts.env}`));
|
|
161
|
+
console.log(chalk_1.default.gray(` tier: ${opts.tier}`));
|
|
162
|
+
console.log(chalk_1.default.gray(` nets: ${opts.networks}\n`));
|
|
163
|
+
const spinner = (0, ora_1.default)(`requesting ${opts.tier} subscription...`).start();
|
|
82
164
|
let result;
|
|
83
165
|
try {
|
|
84
|
-
|
|
85
|
-
// the four-step deploy flow and the new entry-point for allocating an
|
|
86
|
-
// appId on the cluster. The legacy `BaasClient.register()` +
|
|
87
|
-
// `POST /api/deployment/apps` surface was removed (no backward compat
|
|
88
|
-
// per spec §4 hard rules). `subscribe` does not deploy an image, so
|
|
89
|
-
// we synthesise a reasonable default port — the runtime sub-doc is
|
|
90
|
-
// populated at `deploy` time (PR-D), not at init.
|
|
91
|
-
result = await client.deployment.init({ name: appName, port: 3000, services });
|
|
166
|
+
result = await runSubscribe(opts);
|
|
92
167
|
}
|
|
93
168
|
catch (err) {
|
|
94
|
-
spinner.fail(
|
|
169
|
+
spinner.fail(err.message);
|
|
95
170
|
process.exit(1);
|
|
96
171
|
}
|
|
97
|
-
spinner.succeed(`appId
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
172
|
+
spinner.succeed(`subscription active (appId=${result.appId})`);
|
|
173
|
+
if (result.nftSerial !== undefined) {
|
|
174
|
+
console.log(chalk_1.default.gray(` NFT serial: ${result.nftSerial}`));
|
|
175
|
+
}
|
|
176
|
+
if (result.subscriptionId) {
|
|
177
|
+
console.log(chalk_1.default.gray(` subscriptionId: ${result.subscriptionId}`));
|
|
178
|
+
}
|
|
179
|
+
const updates = {
|
|
101
180
|
SUBSCRIPTION_APP_ID: result.appId,
|
|
102
181
|
APP_ID: result.appId,
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
182
|
+
};
|
|
183
|
+
if (result.nftSerial !== undefined) {
|
|
184
|
+
updates.SUBSCRIPTION_NFT_SERIAL = String(result.nftSerial);
|
|
185
|
+
}
|
|
186
|
+
(0, env_1.upsertEnv)(opts.env, updates);
|
|
187
|
+
console.log(chalk_1.default.gray(`\n wrote SUBSCRIPTION_APP_ID${result.nftSerial !== undefined ? ' + SUBSCRIPTION_NFT_SERIAL' : ''} to ${opts.env}`));
|
|
106
188
|
console.log(chalk_1.default.bold.green('\n ✓ subscribed\n'));
|
|
107
|
-
console.log(chalk_1.default.gray(' Next: restart your backend; BaaS endpoints can now bind to this appId.\n'));
|
|
108
189
|
});
|
|
109
190
|
//# sourceMappingURL=subscribe.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscribe.js","sourceRoot":"","sources":["../../src/commands/subscribe.ts"],"names":[],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"subscribe.js","sourceRoot":"","sources":["../../src/commands/subscribe.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `hsuite upgrade --to-tier <T>` — POST /api/v3/subscription/upgrade.
|
|
3
|
+
*
|
|
4
|
+
* If the server returns depositInstructions (top-up), display them and
|
|
5
|
+
* poll /status until PENDING_MINT, then POST /mint — same paid-tier
|
|
6
|
+
* loop as `hsuite subscribe`.
|
|
7
|
+
*
|
|
8
|
+
* Also exposes `hsuite tier-change cancel` as a sibling subcommand so
|
|
9
|
+
* pending upgrades/downgrades can be aborted.
|
|
10
|
+
*/
|
|
11
|
+
import { Command } from 'commander';
|
|
12
|
+
import { SubscriptionClient } from '../_lib/subscription-client';
|
|
13
|
+
type UpgradeOpts = {
|
|
14
|
+
env: string;
|
|
15
|
+
gateway?: string;
|
|
16
|
+
appId?: string;
|
|
17
|
+
toTier: string;
|
|
18
|
+
pollIntervalMs?: number;
|
|
19
|
+
pollTimeoutMs?: number;
|
|
20
|
+
clientFactory?: (baseUrl: string) => SubscriptionClient;
|
|
21
|
+
sleep?: (ms: number) => Promise<void>;
|
|
22
|
+
};
|
|
23
|
+
export declare function runUpgrade(opts: UpgradeOpts): Promise<{
|
|
24
|
+
appId: string;
|
|
25
|
+
toTier: string;
|
|
26
|
+
topUpRequired: boolean;
|
|
27
|
+
effectiveAt?: string | number;
|
|
28
|
+
}>;
|
|
29
|
+
export declare const upgradeCommand: Command;
|
|
30
|
+
type CancelOpts = {
|
|
31
|
+
env: string;
|
|
32
|
+
gateway?: string;
|
|
33
|
+
appId?: string;
|
|
34
|
+
clientFactory?: (baseUrl: string) => SubscriptionClient;
|
|
35
|
+
};
|
|
36
|
+
export declare function runCancelTierChange(opts: CancelOpts): Promise<{
|
|
37
|
+
appId: string;
|
|
38
|
+
}>;
|
|
39
|
+
export declare const tierChangeCommand: Command;
|
|
40
|
+
export {};
|
|
41
|
+
//# sourceMappingURL=upgrade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAAE,kBAAkB,EAAuB,MAAM,6BAA6B,CAAC;AAGtF,KAAK,WAAW,GAAG;IACjB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,kBAAkB,CAAC;IACxD,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,CAAC;AAKF,wBAAsB,UAAU,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC;IAC3D,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,OAAO,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC/B,CAAC,CAuCD;AAiBD,eAAO,MAAM,cAAc,SAsBvB,CAAC;AAML,KAAK,UAAU,GAAG;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,kBAAkB,CAAC;CACzD,CAAC;AAEF,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAQtF;AAoBD,eAAO,MAAM,iBAAiB,SAEC,CAAC"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.tierChangeCommand = exports.upgradeCommand = void 0;
|
|
7
|
+
exports.runUpgrade = runUpgrade;
|
|
8
|
+
exports.runCancelTierChange = runCancelTierChange;
|
|
9
|
+
/**
|
|
10
|
+
* `hsuite upgrade --to-tier <T>` — POST /api/v3/subscription/upgrade.
|
|
11
|
+
*
|
|
12
|
+
* If the server returns depositInstructions (top-up), display them and
|
|
13
|
+
* poll /status until PENDING_MINT, then POST /mint — same paid-tier
|
|
14
|
+
* loop as `hsuite subscribe`.
|
|
15
|
+
*
|
|
16
|
+
* Also exposes `hsuite tier-change cancel` as a sibling subcommand so
|
|
17
|
+
* pending upgrades/downgrades can be aborted.
|
|
18
|
+
*/
|
|
19
|
+
const commander_1 = require("commander");
|
|
20
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
21
|
+
const ora_1 = __importDefault(require("ora"));
|
|
22
|
+
const env_1 = require("../_lib/env");
|
|
23
|
+
const subscription_client_1 = require("../_lib/subscription-client");
|
|
24
|
+
const subscription_env_1 = require("../_lib/subscription-env");
|
|
25
|
+
const defaultSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
26
|
+
async function runUpgrade(opts) {
|
|
27
|
+
if (!opts.toTier)
|
|
28
|
+
throw new Error('--to-tier is required');
|
|
29
|
+
const env = (0, env_1.readEnv)(opts.env);
|
|
30
|
+
const baseUrl = (0, subscription_env_1.requireValidatorUrl)(env, { gateway: opts.gateway });
|
|
31
|
+
const appId = (0, subscription_env_1.requireAppId)(env, { appId: opts.appId });
|
|
32
|
+
const client = (opts.clientFactory ?? ((b) => new subscription_client_1.SubscriptionClient({ baseUrl: b })))(baseUrl);
|
|
33
|
+
const sleep = opts.sleep ?? defaultSleep;
|
|
34
|
+
const res = await client.upgrade(appId, opts.toTier);
|
|
35
|
+
if (!res.success) {
|
|
36
|
+
throw new Error(`upgrade failed: ${res.message ?? 'unknown error'}`);
|
|
37
|
+
}
|
|
38
|
+
if (res.depositInstructions) {
|
|
39
|
+
renderDepositInstructions(res.depositInstructions, opts.toTier);
|
|
40
|
+
const deadline = Date.now() + (opts.pollTimeoutMs ?? 5 * 60 * 1000);
|
|
41
|
+
const interval = opts.pollIntervalMs ?? 5000;
|
|
42
|
+
while (true) {
|
|
43
|
+
const status = await client.status(appId);
|
|
44
|
+
const s = (status.status ?? '').toLowerCase();
|
|
45
|
+
if (s === 'pending_mint' || s === 'active' || s === 'minting')
|
|
46
|
+
break;
|
|
47
|
+
if (Date.now() > deadline) {
|
|
48
|
+
throw new Error('timed out waiting for deposit confirmation');
|
|
49
|
+
}
|
|
50
|
+
await sleep(interval);
|
|
51
|
+
}
|
|
52
|
+
const mint = await client.mint(appId);
|
|
53
|
+
if (!mint.success) {
|
|
54
|
+
throw new Error('mint after upgrade failed');
|
|
55
|
+
}
|
|
56
|
+
return { appId, toTier: opts.toTier, topUpRequired: true, effectiveAt: mint.expiresAt };
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
appId,
|
|
60
|
+
toTier: opts.toTier,
|
|
61
|
+
topUpRequired: false,
|
|
62
|
+
effectiveAt: res.effectiveAt,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function renderDepositInstructions(d, toTier) {
|
|
66
|
+
console.log(chalk_1.default.bold.yellow(`\n Top-up required to upgrade to "${toTier}":`));
|
|
67
|
+
console.log(chalk_1.default.gray(` chain: ${d.chain}`));
|
|
68
|
+
console.log(chalk_1.default.gray(` amount: ${d.amount} (token ${d.tokenId})`));
|
|
69
|
+
console.log(chalk_1.default.gray(` to: ${d.walletAddress}\n`));
|
|
70
|
+
if (d.chain === 'xrpl') {
|
|
71
|
+
console.log(chalk_1.default.cyan(` XUMM deeplink: xumm://xrpl/send?to=${encodeURIComponent(d.walletAddress)}&amount=${encodeURIComponent(d.amount)}&token=${encodeURIComponent(d.tokenId)}\n`));
|
|
72
|
+
}
|
|
73
|
+
console.log(chalk_1.default.gray(' Waiting for deposit confirmation...\n'));
|
|
74
|
+
}
|
|
75
|
+
exports.upgradeCommand = new commander_1.Command('upgrade')
|
|
76
|
+
.description('Upgrade the subscription tier (may require a top-up deposit)')
|
|
77
|
+
.option('--env <file>', 'Env file with subscription appId', '.env.local')
|
|
78
|
+
.option('--gateway <url>', 'Validator/gateway URL (defaults to VALIDATOR_URL in env)')
|
|
79
|
+
.option('--app-id <id>', 'Override SUBSCRIPTION_APP_ID from env')
|
|
80
|
+
.requiredOption('--to-tier <tier>', 'Target tier (starter|professional|enterprise)')
|
|
81
|
+
.action(async (opts) => {
|
|
82
|
+
console.log(chalk_1.default.bold.cyan('\n hsuite upgrade\n'));
|
|
83
|
+
const spinner = (0, ora_1.default)(`upgrading to ${opts.toTier}...`).start();
|
|
84
|
+
try {
|
|
85
|
+
const result = await runUpgrade(opts);
|
|
86
|
+
spinner.succeed(`upgraded to ${result.toTier}${result.topUpRequired ? ' (top-up paid + NFT re-minted)' : ''}`);
|
|
87
|
+
if (result.effectiveAt !== undefined) {
|
|
88
|
+
console.log(chalk_1.default.gray(` effective: ${result.effectiveAt}`));
|
|
89
|
+
}
|
|
90
|
+
console.log(chalk_1.default.bold.green('\n ✓ upgraded\n'));
|
|
91
|
+
}
|
|
92
|
+
catch (err) {
|
|
93
|
+
spinner.fail(err.message);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
async function runCancelTierChange(opts) {
|
|
98
|
+
const env = (0, env_1.readEnv)(opts.env);
|
|
99
|
+
const baseUrl = (0, subscription_env_1.requireValidatorUrl)(env, { gateway: opts.gateway });
|
|
100
|
+
const appId = (0, subscription_env_1.requireAppId)(env, { appId: opts.appId });
|
|
101
|
+
const client = (opts.clientFactory ?? ((b) => new subscription_client_1.SubscriptionClient({ baseUrl: b })))(baseUrl);
|
|
102
|
+
const res = await client.cancelTierChange(appId);
|
|
103
|
+
if (!res.success)
|
|
104
|
+
throw new Error(`tier-change cancel failed: ${res.message ?? 'unknown error'}`);
|
|
105
|
+
return { appId };
|
|
106
|
+
}
|
|
107
|
+
const cancelSubcommand = new commander_1.Command('cancel')
|
|
108
|
+
.description('Cancel a pending tier change')
|
|
109
|
+
.option('--env <file>', 'Env file with subscription appId', '.env.local')
|
|
110
|
+
.option('--gateway <url>', 'Validator/gateway URL (defaults to VALIDATOR_URL in env)')
|
|
111
|
+
.option('--app-id <id>', 'Override SUBSCRIPTION_APP_ID from env')
|
|
112
|
+
.action(async (opts) => {
|
|
113
|
+
console.log(chalk_1.default.bold.cyan('\n hsuite tier-change cancel\n'));
|
|
114
|
+
const spinner = (0, ora_1.default)('cancelling pending tier change...').start();
|
|
115
|
+
try {
|
|
116
|
+
const r = await runCancelTierChange(opts);
|
|
117
|
+
spinner.succeed(`cancelled (appId=${r.appId})`);
|
|
118
|
+
console.log(chalk_1.default.bold.green('\n ✓ cancelled\n'));
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
spinner.fail(err.message);
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
exports.tierChangeCommand = new commander_1.Command('tier-change')
|
|
126
|
+
.description('Manage pending tier changes (cancel)')
|
|
127
|
+
.addCommand(cancelSubcommand);
|
|
128
|
+
//# sourceMappingURL=upgrade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../src/commands/upgrade.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `hsuite usage` — pretty-print today's usage + overage / grace info.
|
|
3
|
+
*
|
|
4
|
+
* Calls both GET /api/v3/subscription/usage/:appId (category breakdown)
|
|
5
|
+
* and GET /api/v3/subscription/usage/status/:appId (overage + grace +
|
|
6
|
+
* projection) when available.
|
|
7
|
+
*/
|
|
8
|
+
import { Command } from 'commander';
|
|
9
|
+
import { SubscriptionClient, UsageStatusResponse, UsageSummaryResponse } from '../_lib/subscription-client';
|
|
10
|
+
type UsageOpts = {
|
|
11
|
+
env: string;
|
|
12
|
+
gateway?: string;
|
|
13
|
+
appId?: string;
|
|
14
|
+
clientFactory?: (baseUrl: string) => SubscriptionClient;
|
|
15
|
+
};
|
|
16
|
+
export declare function runUsage(opts: UsageOpts): Promise<{
|
|
17
|
+
summary: UsageSummaryResponse;
|
|
18
|
+
status: UsageStatusResponse | null;
|
|
19
|
+
}>;
|
|
20
|
+
export declare const usageCommand: Command;
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.d.ts","sourceRoot":"","sources":["../../src/commands/usage.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAGpC,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,oBAAoB,EACrB,MAAM,6BAA6B,CAAC;AAGrC,KAAK,SAAS,GAAG;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,kBAAkB,CAAC;CACzD,CAAC;AAEF,wBAAsB,QAAQ,CAAC,IAAI,EAAE,SAAS,GAAG,OAAO,CAAC;IACvD,OAAO,EAAE,oBAAoB,CAAC;IAC9B,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;CACpC,CAAC,CAeD;AAED,eAAO,MAAM,YAAY,SAgDrB,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.usageCommand = void 0;
|
|
7
|
+
exports.runUsage = runUsage;
|
|
8
|
+
/**
|
|
9
|
+
* `hsuite usage` — pretty-print today's usage + overage / grace info.
|
|
10
|
+
*
|
|
11
|
+
* Calls both GET /api/v3/subscription/usage/:appId (category breakdown)
|
|
12
|
+
* and GET /api/v3/subscription/usage/status/:appId (overage + grace +
|
|
13
|
+
* projection) when available.
|
|
14
|
+
*/
|
|
15
|
+
const commander_1 = require("commander");
|
|
16
|
+
const chalk_1 = __importDefault(require("chalk"));
|
|
17
|
+
const env_1 = require("../_lib/env");
|
|
18
|
+
const subscription_client_1 = require("../_lib/subscription-client");
|
|
19
|
+
const subscription_env_1 = require("../_lib/subscription-env");
|
|
20
|
+
async function runUsage(opts) {
|
|
21
|
+
const env = (0, env_1.readEnv)(opts.env);
|
|
22
|
+
const baseUrl = (0, subscription_env_1.requireValidatorUrl)(env, { gateway: opts.gateway });
|
|
23
|
+
const appId = (0, subscription_env_1.requireAppId)(env, { appId: opts.appId });
|
|
24
|
+
const client = (opts.clientFactory ?? ((b) => new subscription_client_1.SubscriptionClient({ baseUrl: b })))(baseUrl);
|
|
25
|
+
const summary = await client.usage(appId);
|
|
26
|
+
// Status is optional — older clusters may 400 without ConsumptionTracker.
|
|
27
|
+
let status = null;
|
|
28
|
+
try {
|
|
29
|
+
status = await client.usageStatus(appId);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
status = null;
|
|
33
|
+
}
|
|
34
|
+
return { summary, status };
|
|
35
|
+
}
|
|
36
|
+
exports.usageCommand = new commander_1.Command('usage')
|
|
37
|
+
.description("Pretty-print today's usage + overage info")
|
|
38
|
+
.option('--env <file>', 'Env file with subscription appId', '.env.local')
|
|
39
|
+
.option('--gateway <url>', 'Validator/gateway URL (defaults to VALIDATOR_URL in env)')
|
|
40
|
+
.option('--app-id <id>', 'Override SUBSCRIPTION_APP_ID from env')
|
|
41
|
+
.action(async (opts) => {
|
|
42
|
+
console.log(chalk_1.default.bold.cyan('\n hsuite usage\n'));
|
|
43
|
+
try {
|
|
44
|
+
const { summary, status } = await runUsage(opts);
|
|
45
|
+
console.log(chalk_1.default.gray(` app: ${summary.appId}`));
|
|
46
|
+
console.log(chalk_1.default.gray(` total today: ${summary.total} calls`));
|
|
47
|
+
console.log(chalk_1.default.gray(` records: ${summary.recordCount}`));
|
|
48
|
+
if (summary.lastUpdated) {
|
|
49
|
+
console.log(chalk_1.default.gray(` updated: ${summary.lastUpdated}`));
|
|
50
|
+
}
|
|
51
|
+
const byCat = Object.entries(summary.byCategory ?? {});
|
|
52
|
+
if (byCat.length > 0) {
|
|
53
|
+
console.log(chalk_1.default.bold.white('\n by category:'));
|
|
54
|
+
for (const [cat, n] of byCat) {
|
|
55
|
+
console.log(chalk_1.default.gray(` ${cat.padEnd(12)} ${n}`));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (status) {
|
|
59
|
+
console.log(chalk_1.default.bold.white('\n status:'));
|
|
60
|
+
console.log(chalk_1.default.gray(` usage: ${status.usagePercent}% (${status.currentUsage}/${status.dailyLimit})`));
|
|
61
|
+
console.log(chalk_1.default.gray(` overage: ${status.overagePercent}%`));
|
|
62
|
+
console.log(chalk_1.default.gray(` blocked: ${status.blocked}`));
|
|
63
|
+
console.log(chalk_1.default.gray(` inGrace: ${status.inGracePeriod}`));
|
|
64
|
+
if (status.graceExpiresAt) {
|
|
65
|
+
console.log(chalk_1.default.gray(` graceUntil: ${status.graceExpiresAt}`));
|
|
66
|
+
}
|
|
67
|
+
if (status.projectedDaysUntilLimit !== null) {
|
|
68
|
+
console.log(chalk_1.default.gray(` projected: ${status.projectedDaysUntilLimit} day(s) until limit`));
|
|
69
|
+
}
|
|
70
|
+
if (status.suggestUpgrade && status.nextTier) {
|
|
71
|
+
console.log(chalk_1.default.yellow(`\n suggested upgrade: ${status.nextTier.tier} (${status.nextTier.apiCallsPerDay}/day, ${status.nextTier.monthlyPriceHsuite} HSUITE/mo)`));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
console.log('');
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
console.error(chalk_1.default.red(` ${err.message}\n`));
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
//# sourceMappingURL=usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usage.js","sourceRoot":"","sources":["../../src/commands/usage.ts"],"names":[],"mappings":"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"}
|