hivesigner 3.3.5 → 4.1.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/README.md +29 -2
- package/lib/client.d.ts +19 -3
- package/lib/hivesigner.min.js +1 -10
- package/lib/index.d.ts +4 -0
- package/lib/index.js +194 -225
- package/lib/methods/send-operation.method.d.ts +1 -2
- package/lib/methods/send-operations.method.d.ts +1 -2
- package/lib/methods/send-transaction.method.d.ts +1 -2
- package/lib/pkce.d.ts +16 -0
- package/lib/types/callback-function.type.d.ts +1 -1
- package/lib/types/hive.types.d.ts +13 -0
- package/lib/types/index.d.ts +2 -0
- package/lib/types/login-options.interface.d.ts +2 -0
- package/lib/types/send-response.type.d.ts +1 -1
- package/lib/types/token-response.interface.d.ts +8 -0
- package/package.json +11 -18
- package/.babelrc +0 -8
- package/.claude/settings.local.json +0 -12
- package/.eslintignore +0 -3
- package/.eslintrc.js +0 -16
- package/CLAUDE.md +0 -142
- package/docs/CNAME +0 -1
- package/docs/index.html +0 -221
- package/jest.config.js +0 -10
- package/rollup.config.js +0 -12
- package/src/client.spec.ts +0 -455
- package/src/client.ts +0 -317
- package/src/consts/api-url.const.ts +0 -1
- package/src/consts/base-url.const.ts +0 -1
- package/src/consts/beta-url.const.ts +0 -1
- package/src/consts/index.ts +0 -3
- package/src/default-import.spec.ts +0 -10
- package/src/factories/index.ts +0 -1
- package/src/factories/initialize.factory.spec.ts +0 -9
- package/src/factories/initialize.factory.ts +0 -7
- package/src/index.ts +0 -16
- package/src/methods/index.ts +0 -4
- package/src/methods/send-operation.method.spec.ts +0 -47
- package/src/methods/send-operation.method.ts +0 -15
- package/src/methods/send-operations.method.spec.ts +0 -47
- package/src/methods/send-operations.method.ts +0 -15
- package/src/methods/send-transaction.method.spec.ts +0 -47
- package/src/methods/send-transaction.method.ts +0 -15
- package/src/methods/sign.method.spec.ts +0 -60
- package/src/methods/sign.method.ts +0 -22
- package/src/modules-import.spec.ts +0 -11
- package/src/require-import.spec.js +0 -11
- package/src/require-import.spec.ts +0 -10
- package/src/types/callback-function.type.ts +0 -1
- package/src/types/client-config.interface.ts +0 -8
- package/src/types/index.ts +0 -5
- package/src/types/login-options.interface.ts +0 -3
- package/src/types/send-response.type.ts +0 -1
- package/src/types/sign-errors.interface.ts +0 -4
- package/src/utilities/index.ts +0 -1
- package/src/utilities/is-browser.util.ts +0 -3
- package/tsconfig.json +0 -15
- package/webpack.config.js +0 -26
package/lib/index.js
CHANGED
|
@@ -2,80 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var crossFetch = require('cross-fetch');
|
|
6
5
|
var hiveUri = require('hive-uri');
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
const API_URL = 'https://hivesigner.com';
|
|
9
8
|
|
|
10
|
-
|
|
9
|
+
const BASE_URL = 'https://hivesigner.com';
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
Copyright (c) Microsoft Corporation.
|
|
14
|
-
|
|
15
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
16
|
-
purpose with or without fee is hereby granted.
|
|
17
|
-
|
|
18
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
19
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
20
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
21
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
22
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
23
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
24
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
25
|
-
***************************************************************************** */
|
|
26
|
-
|
|
27
|
-
function __awaiter(thisArg, _arguments, P, generator) {
|
|
28
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
29
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
30
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
31
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
32
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
33
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function __generator(thisArg, body) {
|
|
38
|
-
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
39
|
-
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
40
|
-
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
41
|
-
function step(op) {
|
|
42
|
-
if (f) throw new TypeError("Generator is already executing.");
|
|
43
|
-
while (_) try {
|
|
44
|
-
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
45
|
-
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
46
|
-
switch (op[0]) {
|
|
47
|
-
case 0: case 1: t = op; break;
|
|
48
|
-
case 4: _.label++; return { value: op[1], done: false };
|
|
49
|
-
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
50
|
-
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
51
|
-
default:
|
|
52
|
-
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
53
|
-
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
54
|
-
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
55
|
-
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
56
|
-
if (t[2]) _.ops.pop();
|
|
57
|
-
_.trys.pop(); continue;
|
|
58
|
-
}
|
|
59
|
-
op = body.call(thisArg, _);
|
|
60
|
-
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
61
|
-
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
var API_URL = 'https://hivesigner.com';
|
|
66
|
-
|
|
67
|
-
var BASE_URL = 'https://hivesigner.com';
|
|
68
|
-
|
|
69
|
-
var BETA_URL = 'https://hivesigner.com';
|
|
11
|
+
const BETA_URL = 'https://hivesigner.com';
|
|
70
12
|
|
|
71
13
|
function isBrowser() {
|
|
72
14
|
return typeof window !== 'undefined' && !!window;
|
|
73
15
|
}
|
|
74
16
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
var Client = /** @class */ (function () {
|
|
78
|
-
function Client(config) {
|
|
17
|
+
class Client {
|
|
18
|
+
constructor(config) {
|
|
79
19
|
this.apiURL = config.apiURL || API_URL;
|
|
80
20
|
this.app = config.app;
|
|
81
21
|
this.callbackURL = config.callbackURL;
|
|
@@ -83,203 +23,196 @@ var Client = /** @class */ (function () {
|
|
|
83
23
|
this.scope = config.scope;
|
|
84
24
|
this.responseType = config.responseType;
|
|
85
25
|
}
|
|
86
|
-
|
|
26
|
+
setBaseURL() {
|
|
87
27
|
console.warn('The function "setBaseUrl" is deprecated, the base URL is always "https://hivesigner.com", you can only change the API URL with "setApiURL"');
|
|
88
28
|
return this;
|
|
89
|
-
}
|
|
90
|
-
|
|
29
|
+
}
|
|
30
|
+
setApiURL(url) {
|
|
91
31
|
this.apiURL = url;
|
|
92
32
|
return this;
|
|
93
|
-
}
|
|
94
|
-
|
|
33
|
+
}
|
|
34
|
+
setApp(app) {
|
|
95
35
|
this.app = app;
|
|
96
36
|
return this;
|
|
97
|
-
}
|
|
98
|
-
|
|
37
|
+
}
|
|
38
|
+
setCallbackURL(url) {
|
|
99
39
|
this.callbackURL = url;
|
|
100
40
|
return this;
|
|
101
|
-
}
|
|
102
|
-
|
|
41
|
+
}
|
|
42
|
+
setAccessToken(accessToken) {
|
|
103
43
|
this.accessToken = accessToken;
|
|
104
44
|
return this;
|
|
105
|
-
}
|
|
106
|
-
|
|
45
|
+
}
|
|
46
|
+
removeAccessToken() {
|
|
107
47
|
delete this.accessToken;
|
|
108
48
|
return this;
|
|
109
|
-
}
|
|
110
|
-
|
|
49
|
+
}
|
|
50
|
+
setScope(scope) {
|
|
111
51
|
this.scope = scope;
|
|
112
52
|
return this;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* The authorize URL. Pass `options.codeChallenge` (from createPkcePair) to
|
|
56
|
+
* protect a code flow sign-in with PKCE, which a native app needs for a
|
|
57
|
+
* custom scheme callback such as `myapp://callback`.
|
|
58
|
+
*/
|
|
59
|
+
getLoginURL(state, account, options = {}) {
|
|
60
|
+
const redirectUri = encodeURIComponent(this.callbackURL);
|
|
61
|
+
let loginURL = `${BASE_URL}/oauth2/authorize?client_id=${this.app}&redirect_uri=${redirectUri}`;
|
|
117
62
|
if (this.responseType === 'code') {
|
|
118
|
-
loginURL +=
|
|
63
|
+
loginURL += `&response_type=${this.responseType}`;
|
|
119
64
|
}
|
|
120
65
|
if (this.scope) {
|
|
121
|
-
loginURL +=
|
|
66
|
+
loginURL += `&scope=${this.scope.join(',')}`;
|
|
122
67
|
}
|
|
123
68
|
if (state) {
|
|
124
|
-
loginURL +=
|
|
69
|
+
loginURL += `&state=${encodeURIComponent(state)}`;
|
|
125
70
|
}
|
|
126
71
|
if (account) {
|
|
127
|
-
loginURL +=
|
|
72
|
+
loginURL += `&account=${encodeURIComponent(account)}`;
|
|
73
|
+
}
|
|
74
|
+
// PKCE protects a code: the token flow has none, and Hivesigner ignores it there.
|
|
75
|
+
if (options.codeChallenge && this.responseType === 'code') {
|
|
76
|
+
loginURL += `&code_challenge=${encodeURIComponent(options.codeChallenge)}&code_challenge_method=S256`;
|
|
128
77
|
}
|
|
129
78
|
return loginURL;
|
|
130
|
-
}
|
|
131
|
-
|
|
79
|
+
}
|
|
80
|
+
login(options) {
|
|
132
81
|
if (isBrowser()) {
|
|
133
82
|
// @ts-ignore
|
|
134
|
-
window.location = this.getLoginURL(options.state);
|
|
83
|
+
window.location = this.getLoginURL(options.state, undefined, { codeChallenge: options.codeChallenge });
|
|
135
84
|
}
|
|
136
|
-
}
|
|
137
|
-
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Exchange a code for tokens at /api/oauth2/token. With PKCE send the
|
|
88
|
+
* verifier; a native app sends no secret and gets no refresh token. A
|
|
89
|
+
* server may pass its client secret as well.
|
|
90
|
+
*
|
|
91
|
+
* Sent WITHOUT the Authorization header: the API reads that header before
|
|
92
|
+
* the body, so a token this client already holds would be read instead of
|
|
93
|
+
* the code.
|
|
94
|
+
*/
|
|
95
|
+
async exchangeCode(code, codeVerifier, clientSecret) {
|
|
96
|
+
const body = { code };
|
|
97
|
+
if (codeVerifier)
|
|
98
|
+
body.code_verifier = codeVerifier;
|
|
99
|
+
if (clientSecret)
|
|
100
|
+
body.client_secret = clientSecret;
|
|
101
|
+
return (await this.makeRequest(`${this.apiURL}/api/oauth2/token`, 'POST', body, false));
|
|
102
|
+
}
|
|
103
|
+
me(cb) {
|
|
138
104
|
return this.send('me', 'POST', {}, cb);
|
|
139
|
-
}
|
|
140
|
-
|
|
105
|
+
}
|
|
106
|
+
decode(memo, cb) {
|
|
141
107
|
return this.send('decode', 'POST', { memo: memo }, cb);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
voter
|
|
146
|
-
author
|
|
147
|
-
permlink
|
|
148
|
-
weight
|
|
108
|
+
}
|
|
109
|
+
vote(voter, author, permlink, weight, cb) {
|
|
110
|
+
const params = {
|
|
111
|
+
voter,
|
|
112
|
+
author,
|
|
113
|
+
permlink,
|
|
114
|
+
weight
|
|
149
115
|
};
|
|
150
116
|
return this.broadcast([['vote', params]], cb);
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
|
|
117
|
+
}
|
|
118
|
+
comment(parentAuthor, parentPermlink, author, permlink, title, body, jsonMetadata, cb) {
|
|
119
|
+
let json = jsonMetadata;
|
|
154
120
|
if (typeof jsonMetadata !== 'string') {
|
|
155
121
|
json = JSON.stringify(jsonMetadata);
|
|
156
122
|
}
|
|
157
|
-
|
|
123
|
+
const params = {
|
|
158
124
|
parent_author: parentAuthor,
|
|
159
125
|
parent_permlink: parentPermlink,
|
|
160
|
-
author
|
|
161
|
-
permlink
|
|
162
|
-
title
|
|
163
|
-
body
|
|
126
|
+
author,
|
|
127
|
+
permlink,
|
|
128
|
+
title,
|
|
129
|
+
body,
|
|
164
130
|
json_metadata: json
|
|
165
131
|
};
|
|
166
132
|
return this.broadcast([['comment', params]], cb);
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
author
|
|
171
|
-
permlink
|
|
133
|
+
}
|
|
134
|
+
deleteComment(author, permlink, cb) {
|
|
135
|
+
const params = {
|
|
136
|
+
author,
|
|
137
|
+
permlink
|
|
172
138
|
};
|
|
173
139
|
return this.broadcast([['delete_comment', params]], cb);
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
|
|
140
|
+
}
|
|
141
|
+
customJson(requiredAuths, requiredPostingAuths, id, json, cb) {
|
|
142
|
+
const params = {
|
|
177
143
|
required_auths: requiredAuths,
|
|
178
144
|
required_posting_auths: requiredPostingAuths,
|
|
179
|
-
id
|
|
180
|
-
json
|
|
145
|
+
id,
|
|
146
|
+
json
|
|
181
147
|
};
|
|
182
148
|
return this.broadcast([['custom_json', params]], cb);
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
|
|
149
|
+
}
|
|
150
|
+
reblog(account, author, permlink, cb) {
|
|
151
|
+
const json = ['reblog', { account, author, permlink }];
|
|
186
152
|
return this.customJson([], [account], 'follow', JSON.stringify(json), cb);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
|
|
153
|
+
}
|
|
154
|
+
follow(follower, following, cb) {
|
|
155
|
+
const json = ['follow', { follower, following, what: ['blog'] }];
|
|
190
156
|
return this.customJson([], [follower], 'follow', JSON.stringify(json), cb);
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
|
|
157
|
+
}
|
|
158
|
+
unfollow(unfollower, unfollowing, cb) {
|
|
159
|
+
const json = ['follow', { follower: unfollower, following: unfollowing, what: [] }];
|
|
194
160
|
return this.customJson([], [unfollower], 'follow', JSON.stringify(json), cb);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
|
|
161
|
+
}
|
|
162
|
+
ignore(follower, following, cb) {
|
|
163
|
+
const json = ['follow', { follower, following, what: ['ignore'] }];
|
|
198
164
|
return this.customJson([], [follower], 'follow', JSON.stringify(json), cb);
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
account
|
|
165
|
+
}
|
|
166
|
+
claimRewardBalance(account, rewardHive, rewardHbd, rewardVests, cb) {
|
|
167
|
+
const params = {
|
|
168
|
+
account,
|
|
203
169
|
reward_hive: rewardHive,
|
|
204
170
|
reward_hbd: rewardHbd,
|
|
205
171
|
reward_vests: rewardVests
|
|
206
172
|
};
|
|
207
173
|
return this.broadcast([['claim_reward_balance', params]], cb);
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
case 1:
|
|
215
|
-
_a.sent();
|
|
216
|
-
return [2 /*return*/, this.removeAccessToken()];
|
|
217
|
-
}
|
|
218
|
-
});
|
|
219
|
-
});
|
|
220
|
-
};
|
|
221
|
-
Client.prototype.updateUserMetadata = function (metadata, cb) {
|
|
222
|
-
if (metadata === void 0) { metadata = {}; }
|
|
174
|
+
}
|
|
175
|
+
async revokeToken(cb) {
|
|
176
|
+
await this.send('oauth2/token/revoke', 'POST', { token: this.accessToken }, cb);
|
|
177
|
+
return this.removeAccessToken();
|
|
178
|
+
}
|
|
179
|
+
updateUserMetadata(metadata = {}, cb) {
|
|
223
180
|
console.warn('The function "updateUserMetadata" is deprecated.');
|
|
224
181
|
return this.send('me', 'PUT', { user_metadata: metadata }, cb);
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
return
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
Client.prototype.broadcast = function (operations, cb) {
|
|
252
|
-
return this.send('broadcast', 'POST', { operations: operations }, cb);
|
|
253
|
-
};
|
|
254
|
-
Client.prototype.makeRequest = function (url, method, body) {
|
|
255
|
-
return __awaiter(this, void 0, Promise, function () {
|
|
256
|
-
var response, json;
|
|
257
|
-
return __generator(this, function (_a) {
|
|
258
|
-
switch (_a.label) {
|
|
259
|
-
case 0: return [4 /*yield*/, fetch(url, {
|
|
260
|
-
method: method,
|
|
261
|
-
headers: {
|
|
262
|
-
Accept: 'application/json, text/plain, */*',
|
|
263
|
-
'Content-Type': 'application/json',
|
|
264
|
-
Authorization: this.accessToken,
|
|
265
|
-
},
|
|
266
|
-
body: JSON.stringify(body),
|
|
267
|
-
})];
|
|
268
|
-
case 1:
|
|
269
|
-
response = _a.sent();
|
|
270
|
-
return [4 /*yield*/, response.json()];
|
|
271
|
-
case 2:
|
|
272
|
-
json = _a.sent();
|
|
273
|
-
if (response.status !== 200 || json.error) {
|
|
274
|
-
throw json;
|
|
275
|
-
}
|
|
276
|
-
return [2 /*return*/, json];
|
|
277
|
-
}
|
|
278
|
-
});
|
|
182
|
+
}
|
|
183
|
+
async send(route, method, body, cb) {
|
|
184
|
+
const url = `${this.apiURL}/api/${route}`;
|
|
185
|
+
if (!cb) {
|
|
186
|
+
return this.makeRequest(url, method, body);
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
const json = await this.makeRequest(url, method, body);
|
|
190
|
+
return cb(null, json);
|
|
191
|
+
}
|
|
192
|
+
catch (failureResponse) {
|
|
193
|
+
return cb(failureResponse, null);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
broadcast(operations, cb) {
|
|
197
|
+
return this.send('broadcast', 'POST', { operations }, cb);
|
|
198
|
+
}
|
|
199
|
+
async makeRequest(url, method, body, withToken = true) {
|
|
200
|
+
if (typeof globalThis.fetch !== 'function') {
|
|
201
|
+
throw new Error('hivesigner: fetch is not available. Node.js 18+ or a modern browser is required. ' +
|
|
202
|
+
'If you are in an older environment, provide a global fetch polyfill.');
|
|
203
|
+
}
|
|
204
|
+
const response = await globalThis.fetch(url, {
|
|
205
|
+
method,
|
|
206
|
+
headers: Object.assign({ Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json' }, (withToken ? { Authorization: this.accessToken } : {})),
|
|
207
|
+
body: JSON.stringify(body),
|
|
279
208
|
});
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
209
|
+
const json = await response.json();
|
|
210
|
+
if (response.status !== 200 || json.error) {
|
|
211
|
+
throw json;
|
|
212
|
+
}
|
|
213
|
+
return json;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
283
216
|
|
|
284
217
|
function sign(name, params, redirectUri) {
|
|
285
218
|
console.warn('The function "sign" is deprecated.');
|
|
@@ -289,39 +222,39 @@ function sign(name, params, redirectUri) {
|
|
|
289
222
|
error_description: 'Request has an invalid format'
|
|
290
223
|
};
|
|
291
224
|
}
|
|
292
|
-
|
|
225
|
+
let url = `${BASE_URL}/sign/${name}?`;
|
|
293
226
|
url += Object.keys(params)
|
|
294
|
-
.map(
|
|
227
|
+
.map(key => `${key}=${encodeURIComponent(params[key])}`)
|
|
295
228
|
.join('&');
|
|
296
|
-
url += redirectUri ?
|
|
229
|
+
url += redirectUri ? `&redirect_uri=${encodeURIComponent(redirectUri)}` : '';
|
|
297
230
|
return url;
|
|
298
231
|
}
|
|
299
232
|
|
|
300
233
|
function sendOperation(op, params, cb) {
|
|
301
|
-
|
|
302
|
-
|
|
234
|
+
const uri = hiveUri.encodeOp(op, params);
|
|
235
|
+
const webUrl = uri.replace('hive://', `${BETA_URL}/`);
|
|
303
236
|
if (cb && isBrowser()) {
|
|
304
|
-
|
|
237
|
+
const win = window.open(webUrl, '_blank');
|
|
305
238
|
return win.focus();
|
|
306
239
|
}
|
|
307
240
|
return webUrl;
|
|
308
241
|
}
|
|
309
242
|
|
|
310
243
|
function sendOperations(ops, params, cb) {
|
|
311
|
-
|
|
312
|
-
|
|
244
|
+
const uri = hiveUri.encodeOps(ops, params);
|
|
245
|
+
const webUrl = uri.replace('hive://', `${BETA_URL}/`);
|
|
313
246
|
if (cb && isBrowser()) {
|
|
314
|
-
|
|
247
|
+
const win = window.open(webUrl, '_blank');
|
|
315
248
|
return win.focus();
|
|
316
249
|
}
|
|
317
250
|
return webUrl;
|
|
318
251
|
}
|
|
319
252
|
|
|
320
253
|
function sendTransaction(tx, params, cb) {
|
|
321
|
-
|
|
322
|
-
|
|
254
|
+
const uri = hiveUri.encodeTx(tx, params);
|
|
255
|
+
const webUrl = uri.replace('hive://', `${BETA_URL}/`);
|
|
323
256
|
if (cb && isBrowser()) {
|
|
324
|
-
|
|
257
|
+
const win = window.open(webUrl, '_blank');
|
|
325
258
|
return win.focus();
|
|
326
259
|
}
|
|
327
260
|
return webUrl;
|
|
@@ -332,18 +265,54 @@ function Initialize(config) {
|
|
|
332
265
|
return new Client(config);
|
|
333
266
|
}
|
|
334
267
|
|
|
268
|
+
/**
|
|
269
|
+
* PKCE (RFC 7636) for apps that cannot keep a client secret: a native app makes
|
|
270
|
+
* a fresh verifier for every sign-in, sends only its S256 challenge to the
|
|
271
|
+
* authorize page, and proves it holds the verifier when it exchanges the code.
|
|
272
|
+
* See https://hivesigner.com/docs/pkce
|
|
273
|
+
*/
|
|
274
|
+
function subtleCrypto() {
|
|
275
|
+
const c = globalThis.crypto;
|
|
276
|
+
if (!c || !c.subtle || typeof c.getRandomValues !== 'function') {
|
|
277
|
+
throw new Error('hivesigner: Web Crypto is not available. Node.js 20+ or a modern browser is required for PKCE.');
|
|
278
|
+
}
|
|
279
|
+
return c;
|
|
280
|
+
}
|
|
281
|
+
function base64url(bytes) {
|
|
282
|
+
let binary = '';
|
|
283
|
+
bytes.forEach((b) => {
|
|
284
|
+
binary += String.fromCharCode(b);
|
|
285
|
+
});
|
|
286
|
+
const b64 = typeof btoa === 'function' ? btoa(binary) : Buffer.from(binary, 'binary').toString('base64');
|
|
287
|
+
return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
|
288
|
+
}
|
|
289
|
+
/** BASE64URL(SHA256(verifier)), the S256 challenge of a verifier. */
|
|
290
|
+
async function pkceChallengeFor(codeVerifier) {
|
|
291
|
+
const digest = await subtleCrypto().subtle.digest('SHA-256', new TextEncoder().encode(codeVerifier));
|
|
292
|
+
return base64url(new Uint8Array(digest));
|
|
293
|
+
}
|
|
294
|
+
/** A new verifier (32 random bytes, 43 characters) and its S256 challenge. */
|
|
295
|
+
async function createPkcePair() {
|
|
296
|
+
const codeVerifier = base64url(subtleCrypto().getRandomValues(new Uint8Array(32)));
|
|
297
|
+
return { codeVerifier, codeChallenge: await pkceChallengeFor(codeVerifier) };
|
|
298
|
+
}
|
|
299
|
+
|
|
335
300
|
var index = {
|
|
336
|
-
Client
|
|
337
|
-
Initialize
|
|
338
|
-
sendTransaction
|
|
339
|
-
sendOperations
|
|
340
|
-
sendOperation
|
|
341
|
-
sign
|
|
301
|
+
Client,
|
|
302
|
+
Initialize,
|
|
303
|
+
sendTransaction,
|
|
304
|
+
sendOperations,
|
|
305
|
+
sendOperation,
|
|
306
|
+
sign,
|
|
307
|
+
createPkcePair,
|
|
308
|
+
pkceChallengeFor
|
|
342
309
|
};
|
|
343
310
|
|
|
344
311
|
exports.Client = Client;
|
|
345
312
|
exports.Initialize = Initialize;
|
|
346
|
-
exports.
|
|
313
|
+
exports.createPkcePair = createPkcePair;
|
|
314
|
+
exports["default"] = index;
|
|
315
|
+
exports.pkceChallengeFor = pkceChallengeFor;
|
|
347
316
|
exports.sendOperation = sendOperation;
|
|
348
317
|
exports.sendOperations = sendOperations;
|
|
349
318
|
exports.sendTransaction = sendTransaction;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import { Parameters } from 'hive-uri';
|
|
2
|
-
import { CallbackFunction } from '../types';
|
|
3
|
-
import { Operation } from '@hiveio/dhive';
|
|
2
|
+
import { CallbackFunction, Operation } from '../types';
|
|
4
3
|
export declare function sendOperation(op: Operation, params: Parameters, cb: CallbackFunction): string | void;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import { Parameters } from 'hive-uri';
|
|
2
|
-
import { CallbackFunction } from '../types';
|
|
3
|
-
import { Operation } from '@hiveio/dhive';
|
|
2
|
+
import { CallbackFunction, Operation } from '../types';
|
|
4
3
|
export declare function sendOperations(ops: Operation[], params: Parameters, cb: CallbackFunction): string | void;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import { Parameters } from 'hive-uri';
|
|
2
|
-
import { CallbackFunction } from '../types';
|
|
3
|
-
import { Transaction } from '@hiveio/dhive';
|
|
2
|
+
import { CallbackFunction, Transaction } from '../types';
|
|
4
3
|
export declare function sendTransaction(tx: Transaction, params: Parameters, cb: CallbackFunction): string | void;
|
package/lib/pkce.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PKCE (RFC 7636) for apps that cannot keep a client secret: a native app makes
|
|
3
|
+
* a fresh verifier for every sign-in, sends only its S256 challenge to the
|
|
4
|
+
* authorize page, and proves it holds the verifier when it exchanges the code.
|
|
5
|
+
* See https://hivesigner.com/docs/pkce
|
|
6
|
+
*/
|
|
7
|
+
export interface PkcePair {
|
|
8
|
+
/** Kept by the app until the exchange. Never put it in a URL. */
|
|
9
|
+
codeVerifier: string;
|
|
10
|
+
/** Sent as `code_challenge` with `code_challenge_method=S256`. */
|
|
11
|
+
codeChallenge: string;
|
|
12
|
+
}
|
|
13
|
+
/** BASE64URL(SHA256(verifier)), the S256 challenge of a verifier. */
|
|
14
|
+
export declare function pkceChallengeFor(codeVerifier: string): Promise<string>;
|
|
15
|
+
/** A new verifier (32 random bytes, 43 characters) and its S256 challenge. */
|
|
16
|
+
export declare function createPkcePair(): Promise<PkcePair>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type CallbackFunction = (error: any, response: any) => any;
|
package/lib/types/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export
|
|
1
|
+
export type SendResponse = any;
|