shoonya-sdk 1.3.3 → 1.5.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/.puppeteerrc.cjs +70 -0
- package/README.md +84 -31
- package/bun.lock +492 -0
- package/dist/index.cjs +1126 -257
- package/dist/index.d.cts +75 -5
- package/dist/index.d.ts +75 -5
- package/dist/index.js +1116 -247
- package/package.json +7 -2
package/.puppeteerrc.cjs
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
const { existsSync, readdirSync } = require("node:fs");
|
|
2
|
+
const { homedir } = require("node:os");
|
|
3
|
+
const { join } = require("node:path");
|
|
4
|
+
|
|
5
|
+
function resolveChromeExecutablePath() {
|
|
6
|
+
const envPath = process.env.PUPPETEER_EXECUTABLE_PATH;
|
|
7
|
+
if (envPath && existsSync(envPath)) {
|
|
8
|
+
return envPath;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const chromeCacheRoot = join(homedir(), ".cache", "puppeteer", "chrome");
|
|
12
|
+
if (!existsSync(chromeCacheRoot)) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const builds = readdirSync(chromeCacheRoot).sort((a, b) =>
|
|
17
|
+
b.localeCompare(a, undefined, { numeric: true })
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const executableCandidates = [
|
|
21
|
+
["chrome-linux64", "chrome"],
|
|
22
|
+
[
|
|
23
|
+
"chrome-mac",
|
|
24
|
+
"Google Chrome for Testing.app",
|
|
25
|
+
"Contents",
|
|
26
|
+
"MacOS",
|
|
27
|
+
"Google Chrome for Testing",
|
|
28
|
+
],
|
|
29
|
+
[
|
|
30
|
+
"chrome-mac-x64",
|
|
31
|
+
"Google Chrome for Testing.app",
|
|
32
|
+
"Contents",
|
|
33
|
+
"MacOS",
|
|
34
|
+
"Google Chrome for Testing",
|
|
35
|
+
],
|
|
36
|
+
[
|
|
37
|
+
"chrome-mac-arm64",
|
|
38
|
+
"Google Chrome for Testing.app",
|
|
39
|
+
"Contents",
|
|
40
|
+
"MacOS",
|
|
41
|
+
"Google Chrome for Testing",
|
|
42
|
+
],
|
|
43
|
+
["chrome-win64", "chrome.exe"],
|
|
44
|
+
["chrome-win32", "chrome.exe"],
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
for (const build of builds) {
|
|
48
|
+
for (const candidate of executableCandidates) {
|
|
49
|
+
const executablePath = join(chromeCacheRoot, build, ...candidate);
|
|
50
|
+
if (existsSync(executablePath)) {
|
|
51
|
+
return executablePath;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return undefined;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** @type {import('puppeteer').Configuration} */
|
|
60
|
+
module.exports = {
|
|
61
|
+
cacheDirectory: join(homedir(), ".cache", "puppeteer"),
|
|
62
|
+
defaultBrowser: "chrome",
|
|
63
|
+
executablePath: resolveChromeExecutablePath(),
|
|
64
|
+
chrome: {
|
|
65
|
+
skipDownload: true,
|
|
66
|
+
},
|
|
67
|
+
firefox: {
|
|
68
|
+
skipDownload: true,
|
|
69
|
+
},
|
|
70
|
+
};
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Shoonya SDK
|
|
2
2
|
|
|
3
|
-
Wrapper around Shoonya
|
|
3
|
+
Wrapper around Shoonya REST + WebSocket APIs.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -15,58 +15,111 @@ yarn add shoonya-sdk
|
|
|
15
15
|
pnpm add shoonya-sdk
|
|
16
16
|
```
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## Credentials
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Current auth flow uses Shoonya OAuth code exchange (`GenAcsTok`) under the hood.
|
|
21
|
+
|
|
22
|
+
`RestClient` / `WebsocketClient` credentials:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
{
|
|
26
|
+
userId: "FAxxxxx",
|
|
27
|
+
password: "your-login-password",
|
|
28
|
+
twoFa: "your-totp-seed",
|
|
29
|
+
apiKey: "your-secret-code", // from Shoonya API page
|
|
30
|
+
clientId?: "FAxxxxx_U", // optional, defaults to `${userId}_U`
|
|
31
|
+
accountId?: "FAxxxxx", // optional
|
|
32
|
+
vendorCode?: "FAxxxxx_U", // optional
|
|
33
|
+
imei?: "api" // optional
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Quick Start
|
|
21
38
|
|
|
22
39
|
```ts
|
|
23
40
|
import { RestClient, WebsocketClient } from "shoonya-sdk";
|
|
24
41
|
|
|
42
|
+
const credentials = {
|
|
43
|
+
userId: process.env.SHOONYA_USER_ID!,
|
|
44
|
+
password: process.env.SHOONYA_USER_PASSWORD!,
|
|
45
|
+
twoFa: process.env.SHOONYA_TWO_FA!,
|
|
46
|
+
apiKey: process.env.SHOONYA_API_KEY!,
|
|
47
|
+
};
|
|
48
|
+
|
|
25
49
|
const restClient = new RestClient(credentials, { logging: true });
|
|
26
|
-
const wsClient = new WebsocketClient({ logging: true });
|
|
50
|
+
const wsClient = new WebsocketClient({ logging: true });
|
|
27
51
|
|
|
28
|
-
|
|
29
|
-
console.log(`Logged in as ${userDetail.actid}`);
|
|
52
|
+
console.log(await restClient.getAccountLimits());
|
|
30
53
|
|
|
54
|
+
wsClient.on("open", () => console.log("socket opened"));
|
|
31
55
|
wsClient.on("connected", () => {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
wsClient.on("priceUpdate", (data) => {
|
|
36
|
-
console.log(data);
|
|
56
|
+
console.log("ws connected");
|
|
57
|
+
wsClient.subscribe("NSE|26000", "Touchline");
|
|
37
58
|
});
|
|
59
|
+
wsClient.on("subscribed", (token) => console.log("subscribed", token));
|
|
60
|
+
wsClient.on("priceUpdate", (data) => console.log("tick", data));
|
|
61
|
+
wsClient.on("error", (err) => console.error("ws error", err.message));
|
|
62
|
+
wsClient.on("close", () => console.log("ws closed"));
|
|
38
63
|
|
|
39
64
|
wsClient.connect();
|
|
40
65
|
```
|
|
41
66
|
|
|
42
|
-
|
|
67
|
+
`RestClient` options:
|
|
43
68
|
|
|
44
69
|
```ts
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
const wsClient = new WebsocketClient({
|
|
48
|
-
cred: {
|
|
49
|
-
// now you need to pass the credentials here
|
|
50
|
-
},
|
|
70
|
+
new RestClient(credentials, {
|
|
51
71
|
logging: true,
|
|
72
|
+
// baseUrl: "https://api.shoonya.com/NorenWClientAPI/",
|
|
73
|
+
// Optional: set true only if your endpoint expects Bearer header.
|
|
74
|
+
sendBearerAuthHeader: false,
|
|
52
75
|
});
|
|
76
|
+
```
|
|
53
77
|
|
|
54
|
-
|
|
55
|
-
wsClient.subscribe(["NSE|26009", "NSE|26000"]); // Bank Nifty and Nifty 50
|
|
56
|
-
});
|
|
78
|
+
## WebSocket Behavior
|
|
57
79
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
80
|
+
- Primary profile: `wss://api.shoonya.com/NorenWSAPI/` with OAuth handshake (`t: "a"`, `accesstoken`)
|
|
81
|
+
- Connect acknowledgement supports both `ak` and `ck`
|
|
82
|
+
- Optional compatibility fallback to legacy WSTP is available
|
|
83
|
+
- Auto reconnect, token refresh, heartbeat, and resubscribe are built in
|
|
61
84
|
|
|
62
|
-
|
|
85
|
+
`WebsocketClient` options:
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
new WebsocketClient({
|
|
89
|
+
logging: true,
|
|
90
|
+
reconnectInterval: 1000,
|
|
91
|
+
maxRetryAttempt: 3,
|
|
92
|
+
heartbeatInterval: 15000,
|
|
93
|
+
connectAckTimeoutMs: 12000,
|
|
94
|
+
postConnectAckDelayMs: 3000,
|
|
95
|
+
enableLegacyFallback: true,
|
|
96
|
+
enableOauthWstpFallback: false,
|
|
97
|
+
dailyRefreshTime: "09:13+05:30",
|
|
98
|
+
});
|
|
63
99
|
```
|
|
64
100
|
|
|
101
|
+
## Environment Variables
|
|
102
|
+
|
|
103
|
+
- `SHOONYA_USER_ID`
|
|
104
|
+
- `SHOONYA_USER_PASSWORD`
|
|
105
|
+
- `SHOONYA_TWO_FA`
|
|
106
|
+
- `SHOONYA_API_KEY`
|
|
107
|
+
- `SHOONYA_VENDOR_CODE` (optional)
|
|
108
|
+
- `SHOONYA_IMEI` (optional)
|
|
109
|
+
|
|
110
|
+
## Puppeteer/Chrome Config
|
|
111
|
+
|
|
112
|
+
OAuth code generation uses Puppeteer.
|
|
113
|
+
|
|
114
|
+
- `.puppeteerrc.cjs` auto-detects installed Chrome from `~/.cache/puppeteer/chrome`
|
|
115
|
+
- Optional override: `PUPPETEER_EXECUTABLE_PATH`
|
|
116
|
+
- Optional sandbox toggle for server/CI: `PUPPETEER_NO_SANDBOX=true` (or `CI=true`)
|
|
117
|
+
- Optional auth automation speed: `SHOONYA_AUTH_SLOWMO_MS` (default `5`)
|
|
118
|
+
|
|
65
119
|
## Features
|
|
66
120
|
|
|
67
|
-
-
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
- Configurable
|
|
72
|
-
- and more...
|
|
121
|
+
- OAuth-based token exchange (`GenAcsTok`)
|
|
122
|
+
- REST requests send `jKey` in body by default (optional Bearer header via `sendBearerAuthHeader`)
|
|
123
|
+
- WSAPI-first WebSocket flow with fallback support
|
|
124
|
+
- Auto reconnect and token refresh
|
|
125
|
+
- Configurable daily reconnect, heartbeat, and ack timeout
|