Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: unbreak node, undo API changes #24

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,14 @@ SDK for Dash's flavor of the Insight API

# Install

```bash
npm install --save dashsight
```sh
npm install --save [email protected]
```

To use `WebSocket`s in Node.js:

```sh
npm install --save [email protected] [email protected]
```

# Usage
Expand Down
6 changes: 6 additions & 0 deletions bin/ws-listen.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,10 @@ async function main() {
main().catch(function (err) {
console.error("Fail:");
console.error(err.stack || err);
if (err.response) {
console.error(err.response.statusCode);
console.error(err.response.statusText);
console.error(err.response.headers);
console.error(err.response.body);
}
});
92 changes: 69 additions & 23 deletions dashsight.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,6 @@
//@ts-ignore
exports.DashSight = Dashsight;

/**
* @type {RequestInit} defaultOpts
*/
let defaultOpts = {
headers: {
Accept: "application/json",
"Content-Type": "application/json",
},
};

const DUFFS = 100000000;

/** @typedef {import('./').CoreUtxo} CoreUtxo */
Expand Down Expand Up @@ -114,7 +104,7 @@
let utxoResp = await Dashsight.fetch(utxoUrl);

/** @type Array<InsightUtxo> */
let utxos = await utxoResp.json();
let utxos = utxoResp.body;
return utxos;
};

Expand All @@ -135,8 +125,9 @@
let txUrl = `${insightBaseUrl}/tx/${txid}`;
let txResp = await Dashsight.fetch(txUrl);

/** @type InsightTx */
let data = await txResp.json();
/** @type {InsightTx} */
//@ts-ignore
let data = txResp.body;
return data;
};

Expand All @@ -146,7 +137,8 @@
let txResp = await Dashsight.fetch(txUrl);

/** @type {InsightTxResponse} */
let body = await txResp.json();
//@ts-ignore
let body = txResp.body;

let data = await getAllPages(body, addr, maxPages);
return data;
Expand All @@ -163,11 +155,11 @@
let nextResp = await Dashsight.fetch(
`${insightBaseUrl}/txs?address=${addr}&pageNum=${cursor}`,
);
nextResp = await nextResp.json();
let nextBody = nextResp.body;
// Note: this could still be wrong, but I don't think we have
// a better way to page so... whatever
// @ts-ignore
body.txs = body.txs.concat(nextResp?.txs);
body.txs = body.txs.concat(nextBody?.txs);
}
return body;
}
Expand All @@ -189,7 +181,7 @@
// TODO better error check
throw new Error(JSON.stringify(txResp.body, null, 2));
}
return txResp.json();
return txResp.body;
};

/** @type {ToCoreUtxo} */
Expand Down Expand Up @@ -282,26 +274,80 @@
return insight;
};

/** @type {HeadersInit} */
let defaultHeaders = {
Accept: "application/json",
"Content-Type": "application/json",
};

/**
* @param {String | URL | Request} url
* @param {RequestInit} [opts]
* @param {RequestInit} [_opts]
*/
Dashsight.fetch = async function dashfetch(url, opts) {
opts = Object.assign({}, defaultOpts, opts);
Dashsight.fetch = async function dashfetch(url, _opts) {
let opts = Object.assign({ headers: {} }, _opts);
Object.assign(opts.headers, defaultHeaders, _opts?.headers);

if (opts.body) {
opts.body = JSON.stringify(opts.body);
//@ts-ignore
let contentType = opts.headers["Content-Type"] || "";
let isJson = contentType.startsWith("application/json");
if (isJson) {
opts.body = JSON.stringify(opts.body);
}
}

let resp = await fetch(url, opts);
let headers = Object.fromEntries(resp.headers.entries());
let rawBody = await resp.text();
let contentType = resp.headers.get("content-type") || "";
let isJson = contentType.startsWith("application/json");

/** @type {Object|Array<any>|String} */
let body = rawBody;
if (isJson) {
try {
body = JSON.parse(rawBody);
} catch (e) {
// ignore
}
}

let response = {
ok: resp.ok,
statusCode: resp.status, // backwards compat
statusText: resp.statusText,
headers: headers,
body: body,
toJSON: function () {
return {
ok: response.ok,
statusCode: response.statusCode,
statusText: response.statusText,
headers: headers,
body: body,
};
},
get status() {
console.warn(
"deprecated: please use either 'statusText' or 'statusCode' (node.js and browser both have 'status', but flipped)",
);
return resp.statusText;
},
_request: opts,
_response: resp,
};

if (resp.ok) {
return resp;
return response;
}

let err = new Error(
`http request was ${resp.status}, not ok. See err.response for details.`,
);

// @ts-ignore
err.response = resp.json();
err.response = response;
throw err;
};

Expand Down
76 changes: 63 additions & 13 deletions dashsocket.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
/**
* @typedef WsOpts
* @prop {String} [baseUrl] - (deprecated by dashsocketBaseUrl) ex: https://insight.dash.org
* @prop {CookieStore} cookieStore - only needed for insight APIs hosted behind an AWS load balancer
* @prop {import('./').CookieStore?} cookieStore - only needed for insight APIs hosted behind an AWS load balancer
* @prop {Boolean} debug
* @prop {Function} onClose
* @prop {Function} onError
Expand Down Expand Up @@ -47,20 +47,16 @@
let now = Date.now();
let sidUrl = `${dashsocketBaseUrl}/?EIO=3&transport=polling&t=${now}`;

let sidResp = await window.fetch(sidUrl, {
mode: "cors",
credentials: "include",
});
let sidResp = await Ws.fetch(sidUrl);
if (!sidResp.ok) {
let err = new Error("bad response");
// TODO make error type consistent between browser and node?
//@ts-ignore
err.response = sidResp;
throw err;
}

// ex: `97:0{"sid":"xxxx",...}`
let msg = await sidResp.text();
let session = parseSession(msg);
let session = parseSession(sidResp.body || "");
return session;
};

Expand All @@ -75,10 +71,8 @@
let subUrl = `${dashsocketBaseUrl}/?EIO=3&transport=polling&t=${now}&sid=${sid}`;
let body = stringifySub(eventname);

let subResp = await window.fetch(subUrl, {
let subResp = await Ws.fetch(subUrl, {
method: "POST",
mode: "cors",
credentials: "include",
headers: {
"Content-Type": "text/plain;charset=UTF-8",
},
Expand All @@ -91,7 +85,7 @@
throw err;
}

return await subResp.text();
return subResp.body;
};

/*
Expand Down Expand Up @@ -291,7 +285,7 @@
/**
* TODO share with node version
* @param {String} msg
* @returns {SocketIoHello}
* @returns {import('./').SocketIoHello}
*/
function parseSession(msg) {
let colonIndex = msg.indexOf(":");
Expand Down Expand Up @@ -451,4 +445,60 @@
return result;
}
};

/** @type {RequestInit} */
let defaultRequest = {
mode: "cors",
credentials: "include",
};

/**
* @param {String | URL | Request} url
* @param {RequestInit} [_opts]
*/
Ws.fetch = async function dashfetch(url, _opts) {
let opts = Object.assign(defaultRequest, _opts);

let resp = await fetch(url, opts);
// this will not have arrays, only strings
let headers = Object.fromEntries(resp.headers.entries());
let body = await resp.text();

let response = {
ok: resp.ok,
statusCode: resp.status, // backwards compat
statusText: resp.statusText,
headers: headers,
body: body,
toJSON: function () {
return {
ok: response.ok,
statusCode: response.statusCode,
statusText: response.statusText,
headers: headers,
body: body,
};
},
get status() {
console.warn(
"deprecated: please use either 'statusText' or 'statusCode' (node.js and browser both have 'status', but flipped)",
);
return resp.statusText;
},
_request: opts,
_response: resp,
};

if (resp.ok) {
return response;
}

let err = new Error(
`http request was ${resp.status}, not ok. See err.response for details.`,
);

// @ts-ignore
err.response = response;
throw err;
};
})(("undefined" !== typeof module && module.exports) || window);
10 changes: 8 additions & 2 deletions jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */

/* Module Resolution Options */
"moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
"moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */,
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
Expand Down Expand Up @@ -71,6 +71,12 @@
"skipLibCheck": true /* Skip type checking of declaration files. */,
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
},
"include": ["./types.js", "server.js", "lib/**/*.js", "bin/**/*.js"],
"include": [
"./types.js",
"dashsight.js",
"dashsocket.js",
"lib/**/*.js",
"bin/**/*.js"
],
"exclude": ["node_modules"]
}
Loading