@super-protocol/sp-cli 0.0.2 → 0.0.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/README.md +217 -263
- package/bin/dev.js +1 -1
- package/dist/commands/account/get-sppi.d.ts +8 -0
- package/dist/commands/account/get-sppi.js +23 -0
- package/dist/commands/account/info.d.ts +22 -0
- package/dist/commands/account/info.js +46 -0
- package/dist/commands/auth/login.d.ts +6 -11
- package/dist/commands/auth/login.js +28 -76
- package/dist/commands/base.d.ts +2 -4
- package/dist/commands/base.js +8 -10
- package/dist/commands/config/add.js +1 -12
- package/dist/commands/config/base.d.ts +5 -3
- package/dist/commands/config/base.js +30 -14
- package/dist/commands/config/create.js +1 -11
- package/dist/commands/config/list.js +20 -19
- package/dist/commands/config/use.js +5 -3
- package/dist/commands/files/download.d.ts +15 -0
- package/dist/commands/files/download.js +55 -0
- package/dist/commands/files/upload.d.ts +18 -0
- package/dist/commands/files/upload.js +79 -0
- package/dist/commands/storage/base.d.ts +13 -0
- package/dist/commands/storage/base.js +125 -0
- package/dist/commands/storage/create.d.ts +11 -0
- package/dist/commands/storage/create.js +53 -0
- package/dist/commands/storage/select.d.ts +9 -0
- package/dist/commands/storage/select.js +40 -0
- package/dist/commands/storage/show.d.ts +17 -0
- package/dist/commands/storage/show.js +36 -0
- package/dist/commands/storage/update.d.ts +14 -0
- package/dist/commands/storage/update.js +187 -0
- package/dist/commands/workflows/extend-lease.d.ts +17 -0
- package/dist/commands/workflows/extend-lease.js +94 -0
- package/dist/config/config-file.schema.d.ts +4 -4
- package/dist/config/config-file.schema.js +1 -1
- package/dist/config/config.schema.d.ts +25 -15
- package/dist/config/config.schema.js +7 -10
- package/dist/constants.d.ts +5 -0
- package/dist/constants.js +5 -0
- package/dist/errors.d.ts +2 -0
- package/dist/errors.js +2 -0
- package/dist/hooks/finally/shutdown-blockchain.d.ts +3 -0
- package/dist/hooks/finally/shutdown-blockchain.js +8 -0
- package/dist/lib/container.d.ts +7 -7
- package/dist/lib/container.js +48 -26
- package/dist/managers/account-manager.d.ts +1 -0
- package/dist/managers/account-manager.js +27 -13
- package/dist/managers/config-file-manager.d.ts +2 -2
- package/dist/managers/config-file-manager.js +29 -12
- package/dist/middlewares/auth-middleware.js +5 -1
- package/dist/services/auth.service.d.ts +24 -0
- package/dist/services/auth.service.js +93 -0
- package/dist/services/storage.service.d.ts +73 -0
- package/dist/services/storage.service.js +351 -0
- package/dist/utils/helper.d.ts +6 -0
- package/dist/utils/helper.js +23 -0
- package/dist/utils/progress.d.ts +8 -0
- package/dist/utils/progress.js +35 -0
- package/oclif.manifest.json +455 -179
- package/package.json +18 -8
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { select } from '@clack/prompts';
|
|
2
|
+
import { Args, Flags } from '@oclif/core';
|
|
3
|
+
import { Orders } from '@super-protocol/sdk-js';
|
|
4
|
+
import { formatEther, parseEther } from 'viem/utils';
|
|
5
|
+
import { BaseCommand } from '../base.js';
|
|
6
|
+
export default class WorkflowsExtendLease extends BaseCommand {
|
|
7
|
+
static args = {
|
|
8
|
+
orderId: Args.string({ description: 'Order ID', required: true }),
|
|
9
|
+
};
|
|
10
|
+
static description = 'Replenish deposit for a workflow to extend its lease time';
|
|
11
|
+
static examples = [
|
|
12
|
+
'<%= config.bin %> <%= command.id %> <orderId> --sppi 1.5',
|
|
13
|
+
'<%= config.bin %> <%= command.id %> <orderId> --minutes 120',
|
|
14
|
+
'<%= config.bin %> <%= command.id %> <orderId> --sppi 2 --yes',
|
|
15
|
+
];
|
|
16
|
+
static flags = {
|
|
17
|
+
minutes: Flags.integer({ description: 'Time to extend order in minutes (automatically calculates tokens)' }),
|
|
18
|
+
sppi: Flags.string({ description: 'SPPI token amount to add to the order' }),
|
|
19
|
+
yes: Flags.boolean({ char: 'y', default: false, description: 'Skip confirmation prompt' }),
|
|
20
|
+
};
|
|
21
|
+
async init() {
|
|
22
|
+
await super.init();
|
|
23
|
+
await this.container
|
|
24
|
+
.initConfigManager()
|
|
25
|
+
.initAccountManager()
|
|
26
|
+
.initBlockchainConnector()
|
|
27
|
+
.initProviderClient({ enableAuth: true })
|
|
28
|
+
.build();
|
|
29
|
+
}
|
|
30
|
+
async run() {
|
|
31
|
+
const { args, flags } = await this.parse(WorkflowsExtendLease);
|
|
32
|
+
const { providerClient } = this.container;
|
|
33
|
+
try {
|
|
34
|
+
this.logger.info(`Checking order ${args.orderId}`);
|
|
35
|
+
// Get actual per-hour price from blockchain
|
|
36
|
+
const amountPerHour = await Orders.calculateWorkflowPerHourPrice(args.orderId);
|
|
37
|
+
let tokenAmount;
|
|
38
|
+
let minutes;
|
|
39
|
+
if (flags.minutes) {
|
|
40
|
+
// Calculate token amount from minutes
|
|
41
|
+
tokenAmount = (BigInt(amountPerHour) * BigInt(flags.minutes)) / 60n;
|
|
42
|
+
minutes = flags.minutes;
|
|
43
|
+
}
|
|
44
|
+
else if (flags.sppi) {
|
|
45
|
+
// Use provided SPPI amount
|
|
46
|
+
tokenAmount = parseEther(flags.sppi);
|
|
47
|
+
minutes = Number((tokenAmount * 60n) / BigInt(amountPerHour));
|
|
48
|
+
}
|
|
49
|
+
else {
|
|
50
|
+
this.error('Please provide either --sppi or --minutes flag to specify the replenishment amount');
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
// Confirmation prompt
|
|
54
|
+
const confirmed = this.flags.yes || await this.selectPrompt({
|
|
55
|
+
message: `Deposit will be replenished by ${formatEther(tokenAmount)} SPPI. Order time is extended by ${minutes} minutes. Confirm?`,
|
|
56
|
+
options: [
|
|
57
|
+
{ label: 'Yes', value: true },
|
|
58
|
+
{ label: 'No', value: false },
|
|
59
|
+
],
|
|
60
|
+
});
|
|
61
|
+
if (!confirmed) {
|
|
62
|
+
this.logger.info('Operation cancelled by user');
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// Call API to replenish deposit
|
|
66
|
+
const { data, error } = await providerClient.POST('/api/workflows/{orderId}/replenish', {
|
|
67
|
+
body: {
|
|
68
|
+
amount: tokenAmount.toString(),
|
|
69
|
+
},
|
|
70
|
+
params: {
|
|
71
|
+
path: {
|
|
72
|
+
orderId: args.orderId,
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
if (error) {
|
|
77
|
+
this.logger.error({ error }, `Order ${args.orderId} was not replenished`);
|
|
78
|
+
this.error(`Failed to replenish deposit: ${error.message || 'Unknown error'}`);
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
this.logger.info({ data }, 'Deposit replenished successfully');
|
|
82
|
+
this.log('Deposit replenished successfully');
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
86
|
+
this.logger.error({ error }, `Order ${args.orderId} was not replenished`);
|
|
87
|
+
this.error(`Order ${args.orderId} was not replenished: ${errorMessage}`);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async selectPrompt(options) {
|
|
91
|
+
const result = await select(options);
|
|
92
|
+
return this.ensurePromptValue(result);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { Static } from '
|
|
2
|
-
export declare const configFileManagerSchema:
|
|
3
|
-
configs:
|
|
4
|
-
currentConfig:
|
|
1
|
+
import { Static, Type } from 'typebox';
|
|
2
|
+
export declare const configFileManagerSchema: Type.TObject<{
|
|
3
|
+
configs: Type.TArray<Type.TString>;
|
|
4
|
+
currentConfig: Type.TOptional<Type.TString>;
|
|
5
5
|
}>;
|
|
6
6
|
export type ConfigFileManagerData = Static<typeof configFileManagerSchema>;
|
|
@@ -1,23 +1,33 @@
|
|
|
1
|
-
import { Static } from '
|
|
2
|
-
export declare const accountSchema:
|
|
3
|
-
address:
|
|
4
|
-
privateKey:
|
|
1
|
+
import { Static, Type } from 'typebox';
|
|
2
|
+
export declare const accountSchema: Type.TObject<{
|
|
3
|
+
address: Type.TString;
|
|
4
|
+
privateKey: Type.TString;
|
|
5
5
|
}>;
|
|
6
|
-
export declare const authSchema:
|
|
7
|
-
accessKey:
|
|
6
|
+
export declare const authSchema: Type.TObject<{
|
|
7
|
+
accessKey: Type.TString;
|
|
8
8
|
}>;
|
|
9
|
-
export declare const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
export declare const blockchainSchema: Type.TObject<{
|
|
10
|
+
blockchainUrl: Type.TOptional<Type.TString>;
|
|
11
|
+
contractAddress: Type.TString;
|
|
12
|
+
}>;
|
|
13
|
+
export declare const cliConfigSchema: Type.TObject<{
|
|
14
|
+
account: Type.TOptional<Type.TObject<{
|
|
15
|
+
address: Type.TString;
|
|
16
|
+
privateKey: Type.TString;
|
|
17
|
+
}>>;
|
|
18
|
+
auth: Type.TOptional<Type.TObject<{
|
|
19
|
+
accessKey: Type.TString;
|
|
13
20
|
}>>;
|
|
14
|
-
|
|
15
|
-
|
|
21
|
+
blockchain: Type.TOptional<Type.TObject<{
|
|
22
|
+
blockchainUrl: Type.TOptional<Type.TString>;
|
|
23
|
+
contractAddress: Type.TString;
|
|
16
24
|
}>>;
|
|
17
|
-
cookies:
|
|
18
|
-
name:
|
|
19
|
-
providerUrl:
|
|
25
|
+
cookies: Type.TOptional<Type.TUnknown>;
|
|
26
|
+
name: Type.TOptional<Type.TString>;
|
|
27
|
+
providerUrl: Type.TOptional<Type.TString>;
|
|
28
|
+
selectedStorage: Type.TOptional<Type.TString>;
|
|
20
29
|
}>;
|
|
21
30
|
export type CliConfig = Static<typeof cliConfigSchema>;
|
|
22
31
|
export type Account = Static<typeof accountSchema>;
|
|
23
32
|
export type Auth = Static<typeof authSchema>;
|
|
33
|
+
export type Blockchain = Static<typeof blockchainSchema>;
|
|
@@ -1,13 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
FormatRegistry.Set('url', (value) => {
|
|
3
|
-
try {
|
|
4
|
-
const u = new URL(value);
|
|
5
|
-
return u.protocol === 'http:' || u.protocol === 'https:';
|
|
6
|
-
}
|
|
7
|
-
catch {
|
|
8
|
-
return false;
|
|
9
|
-
}
|
|
10
|
-
});
|
|
1
|
+
import { Type } from 'typebox';
|
|
11
2
|
export const accountSchema = Type.Object({
|
|
12
3
|
address: Type.String({ pattern: '^0x[a-fA-F0-9]{40}$' }),
|
|
13
4
|
privateKey: Type.String({ pattern: '^0x[a-fA-F0-9]{64}$' }),
|
|
@@ -15,10 +6,16 @@ export const accountSchema = Type.Object({
|
|
|
15
6
|
export const authSchema = Type.Object({
|
|
16
7
|
accessKey: Type.String(),
|
|
17
8
|
});
|
|
9
|
+
export const blockchainSchema = Type.Object({
|
|
10
|
+
blockchainUrl: Type.Optional(Type.String({ format: 'url' })),
|
|
11
|
+
contractAddress: Type.String({ pattern: '^0x[a-fA-F0-9]{40}$' }),
|
|
12
|
+
});
|
|
18
13
|
export const cliConfigSchema = Type.Object({
|
|
19
14
|
account: Type.Optional(accountSchema),
|
|
20
15
|
auth: Type.Optional(authSchema),
|
|
16
|
+
blockchain: Type.Optional(blockchainSchema),
|
|
21
17
|
cookies: Type.Optional(Type.Unknown()),
|
|
22
18
|
name: Type.Optional(Type.String()),
|
|
23
19
|
providerUrl: Type.Optional(Type.String({ format: 'url' })),
|
|
20
|
+
selectedStorage: Type.Optional(Type.String({ maxLength: 36, minLength: 36 })),
|
|
24
21
|
});
|
package/dist/constants.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
1
|
export declare const FILE_ACCESS_PERMS = 384;
|
|
2
2
|
export declare const DIR_ACCESS_PERMS = 448;
|
|
3
3
|
export declare const PROVIDER_URL = "https://api.dp.superprotocol.com";
|
|
4
|
+
export declare const REFRESH_TOKEN_URI = "/api/auth/refresh-access";
|
|
5
|
+
export declare const S3_ENDPOINT = "https://gateway.storjshare.io";
|
|
6
|
+
export declare const S3_REGION = "us-east-1";
|
|
7
|
+
export declare const DEFAULT_USER_CONFIG_FILE = "default.config.json";
|
|
8
|
+
export declare const DEFAULT_USER_CONFIG_NAME = "Default";
|
package/dist/constants.js
CHANGED
|
@@ -3,3 +3,8 @@ export const FILE_ACCESS_PERMS = 0o600;
|
|
|
3
3
|
// Directory permissions. 'drwx------'
|
|
4
4
|
export const DIR_ACCESS_PERMS = 0o700;
|
|
5
5
|
export const PROVIDER_URL = 'https://api.dp.superprotocol.com';
|
|
6
|
+
export const REFRESH_TOKEN_URI = '/api/auth/refresh-access';
|
|
7
|
+
export const S3_ENDPOINT = 'https://gateway.storjshare.io';
|
|
8
|
+
export const S3_REGION = 'us-east-1';
|
|
9
|
+
export const DEFAULT_USER_CONFIG_FILE = 'default.config.json';
|
|
10
|
+
export const DEFAULT_USER_CONFIG_NAME = 'Default';
|
package/dist/errors.d.ts
CHANGED
package/dist/errors.js
CHANGED
package/dist/lib/container.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ import { ProviderClient } from '@super-protocol/provider-client';
|
|
|
3
3
|
import { AccountManager, ConfigFileManager, ConfigManager } from '../managers/index.js';
|
|
4
4
|
interface RuntimeConfig {
|
|
5
5
|
configFile?: string;
|
|
6
|
-
url?: string;
|
|
7
6
|
}
|
|
8
7
|
export declare class AppContainer {
|
|
9
8
|
readonly cwdDir: string;
|
|
@@ -17,7 +16,6 @@ export declare class AppContainer {
|
|
|
17
16
|
private readonly initQueue;
|
|
18
17
|
private logger;
|
|
19
18
|
private runtimeConfigFile?;
|
|
20
|
-
private runtimeProviderUrl?;
|
|
21
19
|
private constructor();
|
|
22
20
|
static initialize(currentDir: string, config: Config): AppContainer;
|
|
23
21
|
get accountManager(): AccountManager;
|
|
@@ -25,13 +23,15 @@ export declare class AppContainer {
|
|
|
25
23
|
get configManager(): ConfigManager;
|
|
26
24
|
static get container(): AppContainer;
|
|
27
25
|
get providerClient(): ProviderClient;
|
|
28
|
-
build(): Promise<
|
|
29
|
-
initAccountManager(): this;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
build(): Promise<this>;
|
|
27
|
+
initAccountManager(rebuild?: boolean): this;
|
|
28
|
+
initBlockchainConnector(): this;
|
|
29
|
+
initConfigFileManager(rebuild?: boolean): this;
|
|
30
|
+
initConfigManager(rebuild?: boolean): this;
|
|
31
|
+
initProviderClient({ enableAuth, enableCookies, rebuild }?: {
|
|
33
32
|
enableAuth?: boolean;
|
|
34
33
|
enableCookies?: boolean;
|
|
34
|
+
rebuild?: boolean;
|
|
35
35
|
}): this;
|
|
36
36
|
setupRuntimeConfig(config: RuntimeConfig): this;
|
|
37
37
|
private queueInit;
|
package/dist/lib/container.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createProviderClient, loggerMiddleware, requestIdMiddleware, } from '@super-protocol/provider-client';
|
|
2
|
+
import { BlockchainConnector } from '@super-protocol/sdk-js';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import { PROVIDER_URL } from '../constants.js';
|
|
4
5
|
import logger from '../logger.js';
|
|
@@ -17,7 +18,6 @@ export class AppContainer {
|
|
|
17
18
|
initQueue = new Map();
|
|
18
19
|
logger;
|
|
19
20
|
runtimeConfigFile;
|
|
20
|
-
runtimeProviderUrl;
|
|
21
21
|
constructor(cwdDir, oclifConfig) {
|
|
22
22
|
this.cwdDir = cwdDir;
|
|
23
23
|
this.oclifConfig = oclifConfig;
|
|
@@ -61,9 +61,10 @@ export class AppContainer {
|
|
|
61
61
|
}
|
|
62
62
|
async build() {
|
|
63
63
|
await Promise.all(this.initPromises);
|
|
64
|
+
return this;
|
|
64
65
|
}
|
|
65
|
-
initAccountManager() {
|
|
66
|
-
this.initConfigManager();
|
|
66
|
+
initAccountManager(rebuild = true) {
|
|
67
|
+
this.initConfigManager(rebuild);
|
|
67
68
|
return this.queueInit('accountManager', async () => {
|
|
68
69
|
await this.waitFor('configManager');
|
|
69
70
|
if (this._accountManager) {
|
|
@@ -73,9 +74,30 @@ export class AppContainer {
|
|
|
73
74
|
const accountManager = new AccountManager(this.configManager, this.logger);
|
|
74
75
|
await accountManager.init();
|
|
75
76
|
this._accountManager = accountManager;
|
|
77
|
+
}, rebuild);
|
|
78
|
+
}
|
|
79
|
+
initBlockchainConnector() {
|
|
80
|
+
this.initConfigManager();
|
|
81
|
+
return this.queueInit('blockchainConnector', async () => {
|
|
82
|
+
await this.waitFor('configManager');
|
|
83
|
+
let blockchainConfig = await this.configManager.get('blockchain');
|
|
84
|
+
if (!blockchainConfig) {
|
|
85
|
+
await this.waitFor('providerClient');
|
|
86
|
+
const { data, error } = await this.providerClient.GET('/api/config');
|
|
87
|
+
if (error || !data) {
|
|
88
|
+
throw new Error('Could not get configuration from provider');
|
|
89
|
+
}
|
|
90
|
+
blockchainConfig = {
|
|
91
|
+
blockchainUrl: data.blockchainUrl,
|
|
92
|
+
contractAddress: data.contractAddress,
|
|
93
|
+
};
|
|
94
|
+
await this.configManager.set('blockchain', blockchainConfig);
|
|
95
|
+
}
|
|
96
|
+
this.logger.info('Initializing blockchain connector');
|
|
97
|
+
await BlockchainConnector.getInstance().initialize(blockchainConfig);
|
|
76
98
|
});
|
|
77
99
|
}
|
|
78
|
-
initConfigFileManager() {
|
|
100
|
+
initConfigFileManager(rebuild = false) {
|
|
79
101
|
return this.queueInit('configFileManager', async () => {
|
|
80
102
|
if (this._configFileManager) {
|
|
81
103
|
return;
|
|
@@ -85,16 +107,16 @@ export class AppContainer {
|
|
|
85
107
|
});
|
|
86
108
|
await configFileManager.init();
|
|
87
109
|
this._configFileManager = configFileManager;
|
|
88
|
-
});
|
|
110
|
+
}, rebuild);
|
|
89
111
|
}
|
|
90
|
-
initConfigManager() {
|
|
91
|
-
this.initConfigFileManager();
|
|
112
|
+
initConfigManager(rebuild = false) {
|
|
113
|
+
this.initConfigFileManager(rebuild);
|
|
92
114
|
return this.queueInit('configManager', async () => {
|
|
93
115
|
await this.waitFor('configFileManager');
|
|
94
116
|
if (this._configManager) {
|
|
95
117
|
return;
|
|
96
118
|
}
|
|
97
|
-
const configFilePath = this.configFileManager.getCurrentConfigPath();
|
|
119
|
+
const configFilePath = await this.configFileManager.getCurrentConfigPath();
|
|
98
120
|
if (!configFilePath) {
|
|
99
121
|
throw new Error('Config file not found');
|
|
100
122
|
}
|
|
@@ -102,22 +124,32 @@ export class AppContainer {
|
|
|
102
124
|
const configManager = new ConfigManager(configFilePath, this.logger);
|
|
103
125
|
await configManager.init();
|
|
104
126
|
this._configManager = configManager;
|
|
105
|
-
});
|
|
127
|
+
}, rebuild);
|
|
106
128
|
}
|
|
107
|
-
initProviderClient({ enableAuth = true, enableCookies = true } = {}) {
|
|
129
|
+
initProviderClient({ enableAuth = true, enableCookies = true, rebuild = false } = {}) {
|
|
108
130
|
this.initConfigManager();
|
|
109
131
|
return this.queueInit('providerClient', async () => {
|
|
110
|
-
if (this._providerClient) {
|
|
132
|
+
if (this._providerClient && !rebuild) {
|
|
111
133
|
return;
|
|
112
134
|
}
|
|
113
135
|
await this.waitFor('configManager');
|
|
114
|
-
const providerUrl =
|
|
136
|
+
const providerUrl = await this.configManager.get('providerUrl') || PROVIDER_URL;
|
|
115
137
|
this.logger.info('Initializing provider client');
|
|
116
138
|
const providerClient = createProviderClient({
|
|
117
139
|
baseUrl: providerUrl,
|
|
118
140
|
logger: this.logger,
|
|
119
141
|
middlewares: [requestIdMiddleware, loggerMiddleware],
|
|
120
142
|
});
|
|
143
|
+
if (enableCookies) {
|
|
144
|
+
this.logger.info('Initializing cookie middleware');
|
|
145
|
+
const cookiesMiddleware = await createCookieMiddleware(this.configManager, this.logger, providerUrl);
|
|
146
|
+
providerClient.use(cookiesMiddleware);
|
|
147
|
+
}
|
|
148
|
+
if (enableAuth) {
|
|
149
|
+
this.logger.info('Initializing auth middleware');
|
|
150
|
+
const authMiddleware = await createAuthMiddleware(this.configManager, providerClient, this.logger);
|
|
151
|
+
providerClient.use(authMiddleware);
|
|
152
|
+
}
|
|
121
153
|
providerClient.use({
|
|
122
154
|
onRequest: async ({ request }) => {
|
|
123
155
|
const req = request.clone();
|
|
@@ -128,28 +160,18 @@ export class AppContainer {
|
|
|
128
160
|
}
|
|
129
161
|
this.logger.debug({
|
|
130
162
|
body,
|
|
163
|
+
token: req.headers.get('Authorization'),
|
|
131
164
|
url: req.url,
|
|
132
165
|
}, 'Requesting');
|
|
133
166
|
},
|
|
134
167
|
});
|
|
135
|
-
if (enableCookies) {
|
|
136
|
-
this.logger.info('Initializing cookie middleware');
|
|
137
|
-
const cookiesMiddleware = await createCookieMiddleware(this.configManager, this.logger, providerUrl);
|
|
138
|
-
providerClient.use(cookiesMiddleware);
|
|
139
|
-
}
|
|
140
|
-
if (enableAuth) {
|
|
141
|
-
this.logger.info('Initializing auth middleware');
|
|
142
|
-
const authMiddleware = await createAuthMiddleware(this.configManager, providerClient, this.logger);
|
|
143
|
-
providerClient.use(authMiddleware);
|
|
144
|
-
}
|
|
145
168
|
this._providerClient = providerClient;
|
|
146
|
-
});
|
|
169
|
+
}, rebuild);
|
|
147
170
|
}
|
|
148
171
|
setupRuntimeConfig(config) {
|
|
149
172
|
if (this.initQueue.size > 0) {
|
|
150
173
|
throw new Error('Cannot change runtime config after initialization has started');
|
|
151
174
|
}
|
|
152
|
-
this.runtimeProviderUrl = config.url;
|
|
153
175
|
if (config.configFile) {
|
|
154
176
|
this.runtimeConfigFile = path.isAbsolute(config.configFile)
|
|
155
177
|
? config.configFile
|
|
@@ -160,8 +182,8 @@ export class AppContainer {
|
|
|
160
182
|
}
|
|
161
183
|
return this;
|
|
162
184
|
}
|
|
163
|
-
queueInit(name, task) {
|
|
164
|
-
if (!this.initQueue.has(name)) {
|
|
185
|
+
queueInit(name, task, force = false) {
|
|
186
|
+
if (!this.initQueue.has(name) || force) {
|
|
165
187
|
const promise = task();
|
|
166
188
|
this.initQueue.set(name, promise);
|
|
167
189
|
this.initPromises.push(promise);
|
|
@@ -4,9 +4,9 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
4
4
|
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
5
|
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
6
|
};
|
|
7
|
-
import { confirm, password } from '@
|
|
7
|
+
import { confirm, isCancel, password } from '@clack/prompts';
|
|
8
8
|
import { ux } from '@oclif/core';
|
|
9
|
-
import { Value } from '
|
|
9
|
+
import { Value } from 'typebox/value';
|
|
10
10
|
import { Retryable } from 'typescript-retry-decorator';
|
|
11
11
|
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
|
|
12
12
|
import { accountSchema } from '../config/config.schema.js';
|
|
@@ -65,24 +65,38 @@ export class AccountManager {
|
|
|
65
65
|
}
|
|
66
66
|
catch (error) {
|
|
67
67
|
this.logger.warn({ err: error }, 'Incorrect config file');
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
68
|
+
await this.interactWithUser();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async interactWithUser() {
|
|
72
|
+
ux.warn("Account doesn't exist in current configuration");
|
|
73
|
+
const ask = await confirm({
|
|
74
|
+
message: 'Do you want to create a new account?',
|
|
75
|
+
});
|
|
76
|
+
if (isCancel(ask)) {
|
|
77
|
+
ux.error('Operation cancelled.', { exit: 1 });
|
|
78
|
+
}
|
|
79
|
+
if (ask) {
|
|
80
|
+
await this.promptAccount();
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
ux.error('Credentials not generated please check config file and rerun command again', { exit: 1 });
|
|
78
84
|
}
|
|
79
85
|
}
|
|
80
86
|
async promptAccount() {
|
|
81
87
|
const askPrivateKey = await confirm({
|
|
88
|
+
initialValue: false,
|
|
82
89
|
message: 'Do you want to input privateKey?',
|
|
83
90
|
});
|
|
91
|
+
if (isCancel(askPrivateKey)) {
|
|
92
|
+
ux.error('Operation cancelled.', { exit: 1 });
|
|
93
|
+
}
|
|
84
94
|
if (askPrivateKey) {
|
|
85
|
-
const
|
|
95
|
+
const privateKeyInput = await password({ message: 'Please input your privateKey for using in account' });
|
|
96
|
+
if (isCancel(privateKeyInput)) {
|
|
97
|
+
ux.error('Operation cancelled.', { exit: 1 });
|
|
98
|
+
}
|
|
99
|
+
const privateKey = privateKeyInput.trim();
|
|
86
100
|
try {
|
|
87
101
|
const account = await this.createFromKey(privateKey);
|
|
88
102
|
ux.stdout('Your privateKey will be used in config. Keypair created');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { confirm, select } from '@
|
|
1
|
+
import { confirm, select } from '@clack/prompts';
|
|
2
2
|
import { ux } from '@oclif/core';
|
|
3
3
|
import pino from 'pino';
|
|
4
4
|
import { CliConfig } from '../config/config.schema.js';
|
|
@@ -37,7 +37,7 @@ export declare class ConfigFileManager implements IManager {
|
|
|
37
37
|
name: string;
|
|
38
38
|
}>;
|
|
39
39
|
getCurrentConfigFile(): string | undefined;
|
|
40
|
-
getCurrentConfigPath(): string
|
|
40
|
+
getCurrentConfigPath(): Promise<string>;
|
|
41
41
|
importConfig(sourcePath: string, targetName?: string): Promise<string>;
|
|
42
42
|
init(): Promise<void>;
|
|
43
43
|
removeConfig(configName: string): Promise<void>;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { confirm, select } from '@
|
|
1
|
+
import { confirm, isCancel, select } from '@clack/prompts';
|
|
2
2
|
import { ux } from '@oclif/core';
|
|
3
|
-
import { Value } from '@sinclair/typebox/value';
|
|
4
3
|
import * as fs from 'node:fs';
|
|
5
4
|
import path from 'node:path';
|
|
5
|
+
import { Value } from 'typebox/value';
|
|
6
6
|
import { cliConfigSchema } from '../config/config.schema.js';
|
|
7
|
-
import { DIR_ACCESS_PERMS, FILE_ACCESS_PERMS } from '../constants.js';
|
|
7
|
+
import { DEFAULT_USER_CONFIG_FILE, DEFAULT_USER_CONFIG_NAME, DIR_ACCESS_PERMS, FILE_ACCESS_PERMS, } from '../constants.js';
|
|
8
8
|
import { getConfigName } from '../utils/helper.js';
|
|
9
9
|
export class ConfigFileManager {
|
|
10
10
|
logger;
|
|
@@ -78,22 +78,27 @@ export class ConfigFileManager {
|
|
|
78
78
|
configToDelete = config.file;
|
|
79
79
|
}
|
|
80
80
|
else {
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
81
|
+
const selection = await this.selectPrompt({
|
|
82
|
+
message: 'Select configuration to delete:',
|
|
83
|
+
options: configs.map(config => ({
|
|
84
|
+
label: config.name,
|
|
84
85
|
value: config.file,
|
|
85
86
|
})),
|
|
86
|
-
message: 'Select configuration to delete:',
|
|
87
87
|
});
|
|
88
|
+
if (isCancel(selection)) {
|
|
89
|
+
this.ux.stdout('Deletion cancelled');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
configToDelete = selection;
|
|
88
93
|
}
|
|
89
94
|
const configToDeleteData = configs.find(c => c.file === configToDelete);
|
|
90
95
|
const displayName = configToDeleteData?.name || configToDelete;
|
|
91
96
|
if (!force) {
|
|
92
97
|
const confirmed = await this.confirmPrompt({
|
|
93
|
-
|
|
98
|
+
initialValue: false,
|
|
94
99
|
message: `Are you sure you want to delete configuration "${displayName}"?`,
|
|
95
100
|
});
|
|
96
|
-
if (!confirmed) {
|
|
101
|
+
if (isCancel(confirmed) || !confirmed) {
|
|
97
102
|
this.ux.stdout('Deletion cancelled');
|
|
98
103
|
return;
|
|
99
104
|
}
|
|
@@ -160,14 +165,26 @@ export class ConfigFileManager {
|
|
|
160
165
|
}
|
|
161
166
|
return this.configs.currentConfig;
|
|
162
167
|
}
|
|
163
|
-
getCurrentConfigPath() {
|
|
168
|
+
async getCurrentConfigPath() {
|
|
164
169
|
if (this.runtimeConfigFile) {
|
|
165
170
|
return this.runtimeConfigFile;
|
|
166
171
|
}
|
|
167
172
|
if (!this.configs.currentConfig) {
|
|
168
|
-
|
|
173
|
+
try {
|
|
174
|
+
await this.createConfig(DEFAULT_USER_CONFIG_FILE, DEFAULT_USER_CONFIG_NAME);
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
//
|
|
178
|
+
}
|
|
179
|
+
try {
|
|
180
|
+
await this.setCurrentConfig(DEFAULT_USER_CONFIG_FILE);
|
|
181
|
+
}
|
|
182
|
+
catch (error) {
|
|
183
|
+
this.logger.error({ err: error }, 'Failed to set default config');
|
|
184
|
+
throw error;
|
|
185
|
+
}
|
|
169
186
|
}
|
|
170
|
-
return path.join(this.configsDir, this.configs.currentConfig);
|
|
187
|
+
return path.join(this.configsDir, this.configs.currentConfig || DEFAULT_USER_CONFIG_FILE);
|
|
171
188
|
}
|
|
172
189
|
async importConfig(sourcePath, targetName) {
|
|
173
190
|
if (!fs.existsSync(sourcePath)) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { decode } from 'jsonwebtoken';
|
|
2
|
+
import { REFRESH_TOKEN_URI } from '../constants.js';
|
|
2
3
|
import { AuthorizationRequiredError } from '../errors.js';
|
|
3
4
|
function isAccessKeyExpired(accessKey) {
|
|
4
5
|
try {
|
|
@@ -23,7 +24,7 @@ export async function createAuthMiddleware(configManager, providerClient, logger
|
|
|
23
24
|
logger.info('Performed refresh token');
|
|
24
25
|
let refreshResult;
|
|
25
26
|
try {
|
|
26
|
-
refreshResult = await providerClient.POST(
|
|
27
|
+
refreshResult = await providerClient.POST(REFRESH_TOKEN_URI);
|
|
27
28
|
}
|
|
28
29
|
catch (error) {
|
|
29
30
|
logger.error({ err: error }, 'failure refresh token');
|
|
@@ -76,6 +77,9 @@ export async function createAuthMiddleware(configManager, providerClient, logger
|
|
|
76
77
|
}
|
|
77
78
|
const middleware = {
|
|
78
79
|
async onRequest({ request }) {
|
|
80
|
+
if (request.url.endsWith(REFRESH_TOKEN_URI)) {
|
|
81
|
+
return request;
|
|
82
|
+
}
|
|
79
83
|
const accessToken = await ensureAccessKey();
|
|
80
84
|
if (accessToken) {
|
|
81
85
|
request.headers.set('Authorization', `Bearer ${accessToken}`);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ProviderClient } from '@super-protocol/provider-client';
|
|
2
|
+
import pino from 'pino';
|
|
3
|
+
import { AccountManager } from '../managers/account-manager.js';
|
|
4
|
+
import { ConfigManager } from '../managers/config-manager.js';
|
|
5
|
+
export declare class AuthError extends Error {
|
|
6
|
+
}
|
|
7
|
+
export declare class AuthService {
|
|
8
|
+
private readonly accountManager;
|
|
9
|
+
private readonly configManager;
|
|
10
|
+
private readonly providerClient;
|
|
11
|
+
private readonly logger;
|
|
12
|
+
constructor(accountManager: AccountManager, configManager: ConfigManager, providerClient: ProviderClient, logger: pino.BaseLogger);
|
|
13
|
+
auth(): Promise<void>;
|
|
14
|
+
getTokens(nonce: string): Promise<void>;
|
|
15
|
+
getUserNonce(address: string): Promise<{
|
|
16
|
+
error: {
|
|
17
|
+
message: string;
|
|
18
|
+
statusCode: number;
|
|
19
|
+
} | undefined;
|
|
20
|
+
user: {
|
|
21
|
+
nonce?: string;
|
|
22
|
+
} | undefined;
|
|
23
|
+
}>;
|
|
24
|
+
}
|