hivesigner 4.0.0 → 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.
Files changed (52) hide show
  1. package/README.md +16 -2
  2. package/lib/client.d.ts +19 -2
  3. package/lib/hivesigner.min.js +1 -1
  4. package/lib/index.d.ts +4 -0
  5. package/lib/index.js +67 -9
  6. package/lib/pkce.d.ts +16 -0
  7. package/lib/types/index.d.ts +1 -0
  8. package/lib/types/login-options.interface.d.ts +2 -0
  9. package/lib/types/token-response.interface.d.ts +8 -0
  10. package/package.json +4 -1
  11. package/.claude/settings.local.json +0 -12
  12. package/.eslintignore +0 -3
  13. package/.eslintrc.js +0 -16
  14. package/CLAUDE.md +0 -142
  15. package/docs/CNAME +0 -1
  16. package/docs/index.html +0 -221
  17. package/jest.config.js +0 -10
  18. package/rollup.config.js +0 -13
  19. package/src/client.spec.ts +0 -453
  20. package/src/client.ts +0 -318
  21. package/src/consts/api-url.const.ts +0 -1
  22. package/src/consts/base-url.const.ts +0 -1
  23. package/src/consts/beta-url.const.ts +0 -1
  24. package/src/consts/index.ts +0 -3
  25. package/src/default-import.spec.ts +0 -10
  26. package/src/factories/index.ts +0 -1
  27. package/src/factories/initialize.factory.spec.ts +0 -9
  28. package/src/factories/initialize.factory.ts +0 -7
  29. package/src/index.ts +0 -16
  30. package/src/methods/index.ts +0 -4
  31. package/src/methods/send-operation.method.spec.ts +0 -47
  32. package/src/methods/send-operation.method.ts +0 -14
  33. package/src/methods/send-operations.method.spec.ts +0 -47
  34. package/src/methods/send-operations.method.ts +0 -14
  35. package/src/methods/send-transaction.method.spec.ts +0 -47
  36. package/src/methods/send-transaction.method.ts +0 -14
  37. package/src/methods/sign.method.spec.ts +0 -60
  38. package/src/methods/sign.method.ts +0 -22
  39. package/src/modules-import.spec.ts +0 -11
  40. package/src/require-import.spec.js +0 -16
  41. package/src/require-import.spec.ts +0 -10
  42. package/src/types/callback-function.type.ts +0 -1
  43. package/src/types/client-config.interface.ts +0 -8
  44. package/src/types/hive.types.ts +0 -12
  45. package/src/types/index.ts +0 -6
  46. package/src/types/login-options.interface.ts +0 -3
  47. package/src/types/send-response.type.ts +0 -1
  48. package/src/types/sign-errors.interface.ts +0 -4
  49. package/src/utilities/index.ts +0 -1
  50. package/src/utilities/is-browser.util.ts +0 -3
  51. package/tsconfig.json +0 -17
  52. package/webpack.config.js +0 -33
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  # HiveSigner SDK
6
6
 
7
- The official HiveSigner JavaScript SDK, written in Typescript. Library supports both callback and promise functions. Learn more about integration: https://docs.hivesigner.com.
7
+ The official HiveSigner JavaScript SDK, written in Typescript. Library supports both callback and promise functions. Learn more about integration: https://hivesigner.com/docs.
8
8
 
9
9
  ## Upgrading to v4
10
10
 
@@ -49,7 +49,7 @@ or
49
49
 
50
50
  For general information about HiveSigner and setting up your app you can checkout the developer documentation.
51
51
 
52
- **[Developers documentation](https://hivesigner.com/developers)**
52
+ **[Developers documentation](https://hivesigner.com/docs)**
53
53
 
54
54
  ## SDK methods
55
55
 
@@ -93,6 +93,20 @@ After logging in, HiveSigner will redirect the user to the "redirect_uri" specif
93
93
  - __expires_in__: The number of seconds until the access token expires.
94
94
  - __username__: The username of the current user.
95
95
 
96
+ ### Mobile and desktop apps: PKCE
97
+ An app that cannot keep a client secret (a mobile or desktop app) uses the code flow with PKCE. It may then use its own scheme as the callback, such as `myapp://callback`, registered on its app account.
98
+ ```js
99
+ import { Client, createPkcePair } from 'hivesigner';
100
+
101
+ const client = new Client({ app: 'myapp', callbackURL: 'myapp://callback', responseType: 'code', scope: ['posting'] });
102
+
103
+ const { codeVerifier, codeChallenge } = await createPkcePair(); // keep codeVerifier in memory
104
+ const link = client.getLoginURL(state, undefined, { codeChallenge });
105
+ // open link, then on myapp://callback?code=CODE&state=STATE:
106
+ const { access_token, username } = await client.exchangeCode(code, codeVerifier);
107
+ ```
108
+ The code can be exchanged once, within 10 minutes, and only with the verifier. A native app gets no refresh token. A server can pass its client secret as the third argument of `exchangeCode`. `createPkcePair` needs Web Crypto: Node.js 20+ or a modern browser. In React Native, add a `crypto.getRandomValues` and `crypto.subtle` polyfill, or make the pair with a native library and pass the challenge to `getLoginURL`. The rest of the SDK still runs on Node.js 18. Full guide: https://hivesigner.com/docs/pkce
109
+
96
110
  ### Get user profile
97
111
  Once a user is logged in to your app you can call the following method to get the details of their account:
98
112
  ```
package/lib/client.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { CallbackFunction, ClientConfig, LoginOptions, Operation, SendResponse } from './types';
1
+ import { CallbackFunction, ClientConfig, LoginOptions, Operation, SendResponse, TokenResponse } from './types';
2
2
  export declare class Client {
3
3
  apiURL: string;
4
4
  app: string;
@@ -14,8 +14,25 @@ export declare class Client {
14
14
  setAccessToken(accessToken: string): this;
15
15
  removeAccessToken(): this;
16
16
  setScope(scope: string[]): this;
17
- getLoginURL(state: string, account?: string): string;
17
+ /**
18
+ * The authorize URL. Pass `options.codeChallenge` (from createPkcePair) to
19
+ * protect a code flow sign-in with PKCE, which a native app needs for a
20
+ * custom scheme callback such as `myapp://callback`.
21
+ */
22
+ getLoginURL(state: string, account?: string, options?: {
23
+ codeChallenge?: string;
24
+ }): string;
18
25
  login(options: LoginOptions): void;
26
+ /**
27
+ * Exchange a code for tokens at /api/oauth2/token. With PKCE send the
28
+ * verifier; a native app sends no secret and gets no refresh token. A
29
+ * server may pass its client secret as well.
30
+ *
31
+ * Sent WITHOUT the Authorization header: the API reads that header before
32
+ * the body, so a token this client already holds would be read instead of
33
+ * the code.
34
+ */
35
+ exchangeCode(code: string, codeVerifier?: string, clientSecret?: string): Promise<TokenResponse>;
19
36
  me(): Promise<SendResponse>;
20
37
  me(cb: CallbackFunction): Promise<SendResponse>;
21
38
  decode(memo: string): Promise<SendResponse>;
@@ -1 +1 @@
1
- var hivesigner;(()=>{"use strict";var e={536(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.encodeMsg=t.encodeOps=t.encodeOp=t.encodeTx=t.resolveCallback=t.resolveTransaction=t.decode=void 0;var n=o(160);"undefined"==typeof btoa&&(o.g.btoa=function(e){return Buffer.from(e,"binary").toString("base64")}),"undefined"==typeof atob&&(o.g.atob=function(e){return Buffer.from(e,"base64").toString("binary")});var r={"/":"_",_:"/","+":"-","-":"+","=":".",".":"="},s=function(e){return btoa(unescape(encodeURIComponent(e))).replace(/(\+|\/|=)/g,function(e){return r[e]})},i=function(e){return decodeURIComponent(escape(atob(e.replace(/(-|_|\.)/g,function(e){return r[e]}))))};t.decode=function(e){var t=e.slice(0,5),o=new n(e.replace(/^hive:/,"http:"));if("hive:"!==t)throw new Error("Invalid protocol, expected 'hive:' got '"+t+"'");if("sign"!==o.host)throw new Error("Invalid action, expected 'sign' got '"+o.host+"'");var r,s,a=o.pathname.split("/").slice(1),c=a[0],l=a[1];try{r=JSON.parse(i(l))}catch(e){throw e.message="Invalid payload: "+e.message,e}switch(c){case"tx":case"msg":s=r;break;case"op":case"ops":s={ref_block_num:"__ref_block_num",ref_block_prefix:"__ref_block_prefix",expiration:"__expiration",extensions:[],operations:"ops"===c?r:[r]};break;default:throw new Error("Invalid signing action '"+c+"'")}var u=Object.fromEntries(o.query.substring(1).split("&").filter(Boolean).map(function(e){var t=e.split("="),o=t[0],n=t[1],r=void 0===n?"":n;return[decodeURIComponent(o),decodeURIComponent(r)]})),p={};return u.cb&&(p.callback=i(u.cb)),void 0!==u.nb&&(p.no_broadcast=!0),u.a&&(p.authority=u.a),u.s&&(p.signer=u.s),{tx:s,params:p}};var a=/(__(ref_block_(num|prefix)|expiration|signer))/g;t.resolveTransaction=function(e,t,o){var n=t.signer||o.preferred_signer;if(!o.signers.includes(n))throw new Error("Signer '"+n+"' not available");var r={__ref_block_num:o.ref_block_num,__ref_block_prefix:o.ref_block_prefix,__expiration:o.expiration,__signer:n},s=function(e){var t=typeof e;switch("object"===t&&Array.isArray(e)?t="array":null===e&&(t="null"),t){case"string":return e.replace(a,function(e){return r[e]});case"array":return e.map(s);case"object":for(var o={},n=0,i=Object.entries(e);n<i.length;n++){var c=i[n],l=c[0],u=c[1];o[l]=s(u)}return o;default:return e}};return{signer:n,tx:s(e)}};var c=/({{(sig|id|block|txn|data)}})/g;function l(e){var t=[];return e.no_broadcast&&t.push("nb="),e.signer&&t.push("s="+e.signer),e.callback&&t.push("cb="+s(e.callback)),e.authority&&t.push("a="+e.authority),t.length?"?"+t.join("&"):""}function u(e){return s(JSON.stringify(e,null,0))}t.resolveCallback=function(e,t){return e.replace(c,function(e,o,n){return t[n]||""})},t.encodeTx=function(e,t){return void 0===t&&(t={}),"hive://sign/tx/"+u(e)+l(t)},t.encodeOp=function(e,t){return void 0===t&&(t={}),"hive://sign/op/"+u(e)+l(t)},t.encodeOps=function(e,t){return void 0===t&&(t={}),"hive://sign/ops/"+u(e)+l(t)},t.encodeMsg=function(e,t){return void 0===t&&(t={}),"hive://sign/msg/"+u(e)+l(t)}},992(e,t){var o=Object.prototype.hasOwnProperty;function n(e){try{return decodeURIComponent(e.replace(/\+/g," "))}catch(e){return null}}function r(e){try{return encodeURIComponent(e)}catch(e){return null}}t.stringify=function(e,t){t=t||"";var n,s,i=[];for(s in"string"!=typeof t&&(t="?"),e)if(o.call(e,s)){if((n=e[s])||null!=n&&!isNaN(n)||(n=""),s=r(s),n=r(n),null===s||null===n)continue;i.push(s+"="+n)}return i.length?t+i.join("&"):""},t.parse=function(e){for(var t,o=/([^=?#&]+)=?([^&]*)/g,r={};t=o.exec(e);){var s=n(t[1]),i=n(t[2]);null===s||null===i||s in r||(r[s]=i)}return r}},63(e){e.exports=function(e,t){if(t=t.split(":")[0],!(e=+e))return!1;switch(t){case"http":case"ws":return 80!==e;case"https":case"wss":return 443!==e;case"ftp":return 21!==e;case"gopher":return 70!==e;case"file":return!1}return 0!==e}},469(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.Client=void 0;const n=o(629),r=o(779);t.Client=class{constructor(e){this.apiURL=e.apiURL||n.API_URL,this.app=e.app,this.callbackURL=e.callbackURL,this.accessToken=e.accessToken,this.scope=e.scope,this.responseType=e.responseType}setBaseURL(){return console.warn('The function "setBaseUrl" is deprecated, the base URL is always "https://hivesigner.com", you can only change the API URL with "setApiURL"'),this}setApiURL(e){return this.apiURL=e,this}setApp(e){return this.app=e,this}setCallbackURL(e){return this.callbackURL=e,this}setAccessToken(e){return this.accessToken=e,this}removeAccessToken(){return delete this.accessToken,this}setScope(e){return this.scope=e,this}getLoginURL(e,t){const o=encodeURIComponent(this.callbackURL);let r=`${n.BASE_URL}/oauth2/authorize?client_id=${this.app}&redirect_uri=${o}`;return"code"===this.responseType&&(r+=`&response_type=${this.responseType}`),this.scope&&(r+=`&scope=${this.scope.join(",")}`),e&&(r+=`&state=${encodeURIComponent(e)}`),t&&(r+=`&account=${encodeURIComponent(t)}`),r}login(e){(0,r.isBrowser)()&&(window.location=this.getLoginURL(e.state))}me(e){return this.send("me","POST",{},e)}decode(e,t){return this.send("decode","POST",{memo:e},t)}vote(e,t,o,n,r){const s={voter:e,author:t,permlink:o,weight:n};return this.broadcast([["vote",s]],r)}comment(e,t,o,n,r,s,i,a){let c=i;"string"!=typeof i&&(c=JSON.stringify(i));const l={parent_author:e,parent_permlink:t,author:o,permlink:n,title:r,body:s,json_metadata:c};return this.broadcast([["comment",l]],a)}deleteComment(e,t,o){const n={author:e,permlink:t};return this.broadcast([["delete_comment",n]],o)}customJson(e,t,o,n,r){const s={required_auths:e,required_posting_auths:t,id:o,json:n};return this.broadcast([["custom_json",s]],r)}reblog(e,t,o,n){const r=["reblog",{account:e,author:t,permlink:o}];return this.customJson([],[e],"follow",JSON.stringify(r),n)}follow(e,t,o){const n=["follow",{follower:e,following:t,what:["blog"]}];return this.customJson([],[e],"follow",JSON.stringify(n),o)}unfollow(e,t,o){const n=["follow",{follower:e,following:t,what:[]}];return this.customJson([],[e],"follow",JSON.stringify(n),o)}ignore(e,t,o){const n=["follow",{follower:e,following:t,what:["ignore"]}];return this.customJson([],[e],"follow",JSON.stringify(n),o)}claimRewardBalance(e,t,o,n,r){const s={account:e,reward_hive:t,reward_hbd:o,reward_vests:n};return this.broadcast([["claim_reward_balance",s]],r)}async revokeToken(e){return await this.send("oauth2/token/revoke","POST",{token:this.accessToken},e),this.removeAccessToken()}updateUserMetadata(e={},t){return console.warn('The function "updateUserMetadata" is deprecated.'),this.send("me","PUT",{user_metadata:e},t)}async send(e,t,o,n){const r=`${this.apiURL}/api/${e}`;if(!n)return this.makeRequest(r,t,o);try{return n(null,await this.makeRequest(r,t,o))}catch(e){return n(e,null)}}broadcast(e,t){return this.send("broadcast","POST",{operations:e},t)}async makeRequest(e,t,o){if("function"!=typeof globalThis.fetch)throw new Error("hivesigner: fetch is not available. Node.js 18+ or a modern browser is required. If you are in an older environment, provide a global fetch polyfill.");const n=await globalThis.fetch(e,{method:t,headers:{Accept:"application/json, text/plain, */*","Content-Type":"application/json",Authorization:this.accessToken},body:JSON.stringify(o)}),r=await n.json();if(200!==n.status||r.error)throw r;return r}}},944(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.API_URL=void 0,t.API_URL="https://hivesigner.com"},69(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.BASE_URL=void 0,t.BASE_URL="https://hivesigner.com"},290(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.BETA_URL=void 0,t.BETA_URL="https://hivesigner.com"},629(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var r=Object.getOwnPropertyDescriptor(t,o);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,r)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),r=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),r(o(944),t),r(o(69),t),r(o(290),t)},261(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var r=Object.getOwnPropertyDescriptor(t,o);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,r)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),r=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),r(o(7),t)},7(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.Initialize=void 0;const n=o(469);t.Initialize=function(e){return console.warn('The function "Initialize" is deprecated, please use the class "Client" instead.'),new n.Client(e)}},440(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var r=Object.getOwnPropertyDescriptor(t,o);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,r)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),r=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),r(o(469),t),r(o(49),t),r(o(261),t);const s=o(469),i=o(261),a=o(49);t.default={Client:s.Client,Initialize:i.Initialize,sendTransaction:a.sendTransaction,sendOperations:a.sendOperations,sendOperation:a.sendOperation,sign:a.sign}},49(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var r=Object.getOwnPropertyDescriptor(t,o);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,r)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),r=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),r(o(893),t),r(o(640),t),r(o(243),t),r(o(887),t)},640(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.sendOperation=void 0;const n=o(629),r=o(536),s=o(779);t.sendOperation=function(e,t,o){const i=(0,r.encodeOp)(e,t).replace("hive://",`${n.BETA_URL}/`);return o&&(0,s.isBrowser)()?window.open(i,"_blank").focus():i}},243(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.sendOperations=void 0;const n=o(536),r=o(779),s=o(629);t.sendOperations=function(e,t,o){const i=(0,n.encodeOps)(e,t).replace("hive://",`${s.BETA_URL}/`);return o&&(0,r.isBrowser)()?window.open(i,"_blank").focus():i}},887(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.sendTransaction=void 0;const n=o(536),r=o(629),s=o(779);t.sendTransaction=function(e,t,o){const i=(0,n.encodeTx)(e,t).replace("hive://",`${r.BETA_URL}/`);return o&&(0,s.isBrowser)()?window.open(i,"_blank").focus():i}},893(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.sign=void 0;const n=o(629);t.sign=function(e,t,o){if(console.warn('The function "sign" is deprecated.'),"string"!=typeof e||"object"!=typeof t||null===t)return{error:"invalid_request",error_description:"Request has an invalid format"};let r=`${n.BASE_URL}/sign/${e}?`;return r+=Object.keys(t).map(e=>`${e}=${encodeURIComponent(t[e])}`).join("&"),r+=o?`&redirect_uri=${encodeURIComponent(o)}`:"",r}},779(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var r=Object.getOwnPropertyDescriptor(t,o);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,r)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),r=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),r(o(790),t)},790(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.isBrowser=void 0,t.isBrowser=function(){return"undefined"!=typeof window&&!!window}},160(e,t,o){var n=o(63),r=o(992),s=/^[\x00-\x20\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/,i=/[\n\r\t]/g,a=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,c=/:\d+$/,l=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i,u=/^[a-zA-Z]:/;function p(e){return(e||"").toString().replace(s,"")}var d=[["#","hash"],["?","query"],function(e,t){return v(t.protocol)?e.replace(/\\/g,"/"):e},["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d*)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]],h={hash:1,query:1};function f(e){var t,n=("undefined"!=typeof window?window:void 0!==o.g?o.g:"undefined"!=typeof self?self:{}).location||{},r={},s=typeof(e=e||n);if("blob:"===e.protocol)r=new g(unescape(e.pathname),{});else if("string"===s)for(t in r=new g(e,{}),h)delete r[t];else if("object"===s){for(t in e)t in h||(r[t]=e[t]);void 0===r.slashes&&(r.slashes=a.test(e.href))}return r}function v(e){return"file:"===e||"ftp:"===e||"http:"===e||"https:"===e||"ws:"===e||"wss:"===e}function b(e,t){e=(e=p(e)).replace(i,""),t=t||{};var o,n=l.exec(e),r=n[1]?n[1].toLowerCase():"",s=!!n[2],a=!!n[3],c=0;return s?a?(o=n[2]+n[3]+n[4],c=n[2].length+n[3].length):(o=n[2]+n[4],c=n[2].length):a?(o=n[3]+n[4],c=n[3].length):o=n[4],"file:"===r?c>=2&&(o=o.slice(2)):v(r)?o=n[4]:r?s&&(o=o.slice(2)):c>=2&&v(t.protocol)&&(o=n[4]),{protocol:r,slashes:s||v(r),slashesCount:c,rest:o}}function g(e,t,o){if(e=(e=p(e)).replace(i,""),!(this instanceof g))return new g(e,t,o);var s,a,c,l,h,_,m=d.slice(),w=typeof t,y=this,O=0;for("object"!==w&&"string"!==w&&(o=t,t=null),o&&"function"!=typeof o&&(o=r.parse),s=!(a=b(e||"",t=f(t))).protocol&&!a.slashes,y.slashes=a.slashes||s&&t.slashes,y.protocol=a.protocol||t.protocol||"",e=a.rest,("file:"===a.protocol&&(2!==a.slashesCount||u.test(e))||!a.slashes&&(a.protocol||a.slashesCount<2||!v(y.protocol)))&&(m[3]=[/(.*)/,"pathname"]);O<m.length;O++)"function"!=typeof(l=m[O])?(c=l[0],_=l[1],c!=c?y[_]=e:"string"==typeof c?~(h="@"===c?e.lastIndexOf(c):e.indexOf(c))&&("number"==typeof l[2]?(y[_]=e.slice(0,h),e=e.slice(h+l[2])):(y[_]=e.slice(h),e=e.slice(0,h))):(h=c.exec(e))&&(y[_]=h[1],e=e.slice(0,h.index)),y[_]=y[_]||s&&l[3]&&t[_]||"",l[4]&&(y[_]=y[_].toLowerCase())):e=l(e,y);o&&(y.query=o(y.query)),s&&t.slashes&&"/"!==y.pathname.charAt(0)&&(""!==y.pathname||""!==t.pathname)&&(y.pathname=function(e,t){if(""===e)return t;for(var o=(t||"/").split("/").slice(0,-1).concat(e.split("/")),n=o.length,r=o[n-1],s=!1,i=0;n--;)"."===o[n]?o.splice(n,1):".."===o[n]?(o.splice(n,1),i++):i&&(0===n&&(s=!0),o.splice(n,1),i--);return s&&o.unshift(""),"."!==r&&".."!==r||o.push(""),o.join("/")}(y.pathname,t.pathname)),"/"!==y.pathname.charAt(0)&&v(y.protocol)&&(y.pathname="/"+y.pathname),n(y.port,y.protocol)||(y.host=y.hostname,y.port=""),y.username=y.password="",y.auth&&(~(h=y.auth.indexOf(":"))?(y.username=y.auth.slice(0,h),y.username=encodeURIComponent(decodeURIComponent(y.username)),y.password=y.auth.slice(h+1),y.password=encodeURIComponent(decodeURIComponent(y.password))):y.username=encodeURIComponent(decodeURIComponent(y.auth)),y.auth=y.password?y.username+":"+y.password:y.username),y.origin="file:"!==y.protocol&&v(y.protocol)&&y.host?y.protocol+"//"+y.host:"null",y.href=y.toString()}g.prototype={set:function(e,t,o){var s=this;switch(e){case"query":"string"==typeof t&&t.length&&(t=(o||r.parse)(t)),s[e]=t;break;case"port":s[e]=t,n(t,s.protocol)?t&&(s.host=s.hostname+":"+t):(s.host=s.hostname,s[e]="");break;case"hostname":s[e]=t,s.port&&(t+=":"+s.port),s.host=t;break;case"host":s[e]=t,c.test(t)?(t=t.split(":"),s.port=t.pop(),s.hostname=t.join(":")):(s.hostname=t,s.port="");break;case"protocol":s.protocol=t.toLowerCase(),s.slashes=!o;break;case"pathname":case"hash":if(t){var i="pathname"===e?"/":"#";s[e]=t.charAt(0)!==i?i+t:t}else s[e]=t;break;case"username":case"password":s[e]=encodeURIComponent(t);break;case"auth":var a=t.indexOf(":");~a?(s.username=t.slice(0,a),s.username=encodeURIComponent(decodeURIComponent(s.username)),s.password=t.slice(a+1),s.password=encodeURIComponent(decodeURIComponent(s.password))):s.username=encodeURIComponent(decodeURIComponent(t))}for(var l=0;l<d.length;l++){var u=d[l];u[4]&&(s[u[1]]=s[u[1]].toLowerCase())}return s.auth=s.password?s.username+":"+s.password:s.username,s.origin="file:"!==s.protocol&&v(s.protocol)&&s.host?s.protocol+"//"+s.host:"null",s.href=s.toString(),s},toString:function(e){e&&"function"==typeof e||(e=r.stringify);var t,o=this,n=o.host,s=o.protocol;s&&":"!==s.charAt(s.length-1)&&(s+=":");var i=s+(o.protocol&&o.slashes||v(o.protocol)?"//":"");return o.username?(i+=o.username,o.password&&(i+=":"+o.password),i+="@"):o.password?(i+=":"+o.password,i+="@"):"file:"!==o.protocol&&v(o.protocol)&&!n&&"/"!==o.pathname&&(i+="@"),(":"===n[n.length-1]||c.test(o.hostname)&&!o.port)&&(n+=":"),i+=n+o.pathname,(t="object"==typeof o.query?e(o.query):o.query)&&(i+="?"!==t.charAt(0)?"?"+t:t),o.hash&&(i+=o.hash),i}},g.extractProtocol=b,g.location=f,g.trimLeft=p,g.qs=r,e.exports=g}},t={};function o(n){var r=t[n];if(void 0!==r)return r.exports;var s=t[n]={exports:{}};return e[n].call(s.exports,s,s.exports,o),s.exports}o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var n=o(440);hivesigner=n})();
1
+ var hivesigner;(()=>{"use strict";var e={536(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.encodeMsg=t.encodeOps=t.encodeOp=t.encodeTx=t.resolveCallback=t.resolveTransaction=t.decode=void 0;var n=o(160);"undefined"==typeof btoa&&(o.g.btoa=function(e){return Buffer.from(e,"binary").toString("base64")}),"undefined"==typeof atob&&(o.g.atob=function(e){return Buffer.from(e,"base64").toString("binary")});var r={"/":"_",_:"/","+":"-","-":"+","=":".",".":"="},s=function(e){return btoa(unescape(encodeURIComponent(e))).replace(/(\+|\/|=)/g,function(e){return r[e]})},i=function(e){return decodeURIComponent(escape(atob(e.replace(/(-|_|\.)/g,function(e){return r[e]}))))};t.decode=function(e){var t=e.slice(0,5),o=new n(e.replace(/^hive:/,"http:"));if("hive:"!==t)throw new Error("Invalid protocol, expected 'hive:' got '"+t+"'");if("sign"!==o.host)throw new Error("Invalid action, expected 'sign' got '"+o.host+"'");var r,s,a=o.pathname.split("/").slice(1),c=a[0],l=a[1];try{r=JSON.parse(i(l))}catch(e){throw e.message="Invalid payload: "+e.message,e}switch(c){case"tx":case"msg":s=r;break;case"op":case"ops":s={ref_block_num:"__ref_block_num",ref_block_prefix:"__ref_block_prefix",expiration:"__expiration",extensions:[],operations:"ops"===c?r:[r]};break;default:throw new Error("Invalid signing action '"+c+"'")}var u=Object.fromEntries(o.query.substring(1).split("&").filter(Boolean).map(function(e){var t=e.split("="),o=t[0],n=t[1],r=void 0===n?"":n;return[decodeURIComponent(o),decodeURIComponent(r)]})),p={};return u.cb&&(p.callback=i(u.cb)),void 0!==u.nb&&(p.no_broadcast=!0),u.a&&(p.authority=u.a),u.s&&(p.signer=u.s),{tx:s,params:p}};var a=/(__(ref_block_(num|prefix)|expiration|signer))/g;t.resolveTransaction=function(e,t,o){var n=t.signer||o.preferred_signer;if(!o.signers.includes(n))throw new Error("Signer '"+n+"' not available");var r={__ref_block_num:o.ref_block_num,__ref_block_prefix:o.ref_block_prefix,__expiration:o.expiration,__signer:n},s=function(e){var t=typeof e;switch("object"===t&&Array.isArray(e)?t="array":null===e&&(t="null"),t){case"string":return e.replace(a,function(e){return r[e]});case"array":return e.map(s);case"object":for(var o={},n=0,i=Object.entries(e);n<i.length;n++){var c=i[n],l=c[0],u=c[1];o[l]=s(u)}return o;default:return e}};return{signer:n,tx:s(e)}};var c=/({{(sig|id|block|txn|data)}})/g;function l(e){var t=[];return e.no_broadcast&&t.push("nb="),e.signer&&t.push("s="+e.signer),e.callback&&t.push("cb="+s(e.callback)),e.authority&&t.push("a="+e.authority),t.length?"?"+t.join("&"):""}function u(e){return s(JSON.stringify(e,null,0))}t.resolveCallback=function(e,t){return e.replace(c,function(e,o,n){return t[n]||""})},t.encodeTx=function(e,t){return void 0===t&&(t={}),"hive://sign/tx/"+u(e)+l(t)},t.encodeOp=function(e,t){return void 0===t&&(t={}),"hive://sign/op/"+u(e)+l(t)},t.encodeOps=function(e,t){return void 0===t&&(t={}),"hive://sign/ops/"+u(e)+l(t)},t.encodeMsg=function(e,t){return void 0===t&&(t={}),"hive://sign/msg/"+u(e)+l(t)}},992(e,t){var o=Object.prototype.hasOwnProperty;function n(e){try{return decodeURIComponent(e.replace(/\+/g," "))}catch(e){return null}}function r(e){try{return encodeURIComponent(e)}catch(e){return null}}t.stringify=function(e,t){t=t||"";var n,s,i=[];for(s in"string"!=typeof t&&(t="?"),e)if(o.call(e,s)){if((n=e[s])||null!=n&&!isNaN(n)||(n=""),s=r(s),n=r(n),null===s||null===n)continue;i.push(s+"="+n)}return i.length?t+i.join("&"):""},t.parse=function(e){for(var t,o=/([^=?#&]+)=?([^&]*)/g,r={};t=o.exec(e);){var s=n(t[1]),i=n(t[2]);null===s||null===i||s in r||(r[s]=i)}return r}},63(e){e.exports=function(e,t){if(t=t.split(":")[0],!(e=+e))return!1;switch(t){case"http":case"ws":return 80!==e;case"https":case"wss":return 443!==e;case"ftp":return 21!==e;case"gopher":return 70!==e;case"file":return!1}return 0!==e}},469(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.Client=void 0;const n=o(629),r=o(779);t.Client=class{constructor(e){this.apiURL=e.apiURL||n.API_URL,this.app=e.app,this.callbackURL=e.callbackURL,this.accessToken=e.accessToken,this.scope=e.scope,this.responseType=e.responseType}setBaseURL(){return console.warn('The function "setBaseUrl" is deprecated, the base URL is always "https://hivesigner.com", you can only change the API URL with "setApiURL"'),this}setApiURL(e){return this.apiURL=e,this}setApp(e){return this.app=e,this}setCallbackURL(e){return this.callbackURL=e,this}setAccessToken(e){return this.accessToken=e,this}removeAccessToken(){return delete this.accessToken,this}setScope(e){return this.scope=e,this}getLoginURL(e,t,o={}){const r=encodeURIComponent(this.callbackURL);let s=`${n.BASE_URL}/oauth2/authorize?client_id=${this.app}&redirect_uri=${r}`;return"code"===this.responseType&&(s+=`&response_type=${this.responseType}`),this.scope&&(s+=`&scope=${this.scope.join(",")}`),e&&(s+=`&state=${encodeURIComponent(e)}`),t&&(s+=`&account=${encodeURIComponent(t)}`),o.codeChallenge&&"code"===this.responseType&&(s+=`&code_challenge=${encodeURIComponent(o.codeChallenge)}&code_challenge_method=S256`),s}login(e){(0,r.isBrowser)()&&(window.location=this.getLoginURL(e.state,void 0,{codeChallenge:e.codeChallenge}))}async exchangeCode(e,t,o){const n={code:e};return t&&(n.code_verifier=t),o&&(n.client_secret=o),await this.makeRequest(`${this.apiURL}/api/oauth2/token`,"POST",n,!1)}me(e){return this.send("me","POST",{},e)}decode(e,t){return this.send("decode","POST",{memo:e},t)}vote(e,t,o,n,r){const s={voter:e,author:t,permlink:o,weight:n};return this.broadcast([["vote",s]],r)}comment(e,t,o,n,r,s,i,a){let c=i;"string"!=typeof i&&(c=JSON.stringify(i));const l={parent_author:e,parent_permlink:t,author:o,permlink:n,title:r,body:s,json_metadata:c};return this.broadcast([["comment",l]],a)}deleteComment(e,t,o){const n={author:e,permlink:t};return this.broadcast([["delete_comment",n]],o)}customJson(e,t,o,n,r){const s={required_auths:e,required_posting_auths:t,id:o,json:n};return this.broadcast([["custom_json",s]],r)}reblog(e,t,o,n){const r=["reblog",{account:e,author:t,permlink:o}];return this.customJson([],[e],"follow",JSON.stringify(r),n)}follow(e,t,o){const n=["follow",{follower:e,following:t,what:["blog"]}];return this.customJson([],[e],"follow",JSON.stringify(n),o)}unfollow(e,t,o){const n=["follow",{follower:e,following:t,what:[]}];return this.customJson([],[e],"follow",JSON.stringify(n),o)}ignore(e,t,o){const n=["follow",{follower:e,following:t,what:["ignore"]}];return this.customJson([],[e],"follow",JSON.stringify(n),o)}claimRewardBalance(e,t,o,n,r){const s={account:e,reward_hive:t,reward_hbd:o,reward_vests:n};return this.broadcast([["claim_reward_balance",s]],r)}async revokeToken(e){return await this.send("oauth2/token/revoke","POST",{token:this.accessToken},e),this.removeAccessToken()}updateUserMetadata(e={},t){return console.warn('The function "updateUserMetadata" is deprecated.'),this.send("me","PUT",{user_metadata:e},t)}async send(e,t,o,n){const r=`${this.apiURL}/api/${e}`;if(!n)return this.makeRequest(r,t,o);try{return n(null,await this.makeRequest(r,t,o))}catch(e){return n(e,null)}}broadcast(e,t){return this.send("broadcast","POST",{operations:e},t)}async makeRequest(e,t,o,n=!0){if("function"!=typeof globalThis.fetch)throw new Error("hivesigner: fetch is not available. Node.js 18+ or a modern browser is required. If you are in an older environment, provide a global fetch polyfill.");const r=await globalThis.fetch(e,{method:t,headers:Object.assign({Accept:"application/json, text/plain, */*","Content-Type":"application/json"},n?{Authorization:this.accessToken}:{}),body:JSON.stringify(o)}),s=await r.json();if(200!==r.status||s.error)throw s;return s}}},944(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.API_URL=void 0,t.API_URL="https://hivesigner.com"},69(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.BASE_URL=void 0,t.BASE_URL="https://hivesigner.com"},290(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.BETA_URL=void 0,t.BETA_URL="https://hivesigner.com"},629(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var r=Object.getOwnPropertyDescriptor(t,o);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,r)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),r=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),r(o(944),t),r(o(69),t),r(o(290),t)},261(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var r=Object.getOwnPropertyDescriptor(t,o);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,r)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),r=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),r(o(7),t)},7(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.Initialize=void 0;const n=o(469);t.Initialize=function(e){return console.warn('The function "Initialize" is deprecated, please use the class "Client" instead.'),new n.Client(e)}},440(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var r=Object.getOwnPropertyDescriptor(t,o);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,r)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),r=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),r(o(469),t),r(o(49),t),r(o(261),t),r(o(295),t);const s=o(469),i=o(261),a=o(49),c=o(295);t.default={Client:s.Client,Initialize:i.Initialize,sendTransaction:a.sendTransaction,sendOperations:a.sendOperations,sendOperation:a.sendOperation,sign:a.sign,createPkcePair:c.createPkcePair,pkceChallengeFor:c.pkceChallengeFor}},49(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var r=Object.getOwnPropertyDescriptor(t,o);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,r)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),r=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),r(o(893),t),r(o(640),t),r(o(243),t),r(o(887),t)},640(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.sendOperation=void 0;const n=o(629),r=o(536),s=o(779);t.sendOperation=function(e,t,o){const i=(0,r.encodeOp)(e,t).replace("hive://",`${n.BETA_URL}/`);return o&&(0,s.isBrowser)()?window.open(i,"_blank").focus():i}},243(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.sendOperations=void 0;const n=o(536),r=o(779),s=o(629);t.sendOperations=function(e,t,o){const i=(0,n.encodeOps)(e,t).replace("hive://",`${s.BETA_URL}/`);return o&&(0,r.isBrowser)()?window.open(i,"_blank").focus():i}},887(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.sendTransaction=void 0;const n=o(536),r=o(629),s=o(779);t.sendTransaction=function(e,t,o){const i=(0,n.encodeTx)(e,t).replace("hive://",`${r.BETA_URL}/`);return o&&(0,s.isBrowser)()?window.open(i,"_blank").focus():i}},893(e,t,o){Object.defineProperty(t,"__esModule",{value:!0}),t.sign=void 0;const n=o(629);t.sign=function(e,t,o){if(console.warn('The function "sign" is deprecated.'),"string"!=typeof e||"object"!=typeof t||null===t)return{error:"invalid_request",error_description:"Request has an invalid format"};let r=`${n.BASE_URL}/sign/${e}?`;return r+=Object.keys(t).map(e=>`${e}=${encodeURIComponent(t[e])}`).join("&"),r+=o?`&redirect_uri=${encodeURIComponent(o)}`:"",r}},295(e,t){function o(){const e=globalThis.crypto;if(!e||!e.subtle||"function"!=typeof e.getRandomValues)throw new Error("hivesigner: Web Crypto is not available. Node.js 20+ or a modern browser is required for PKCE.");return e}function n(e){let t="";return e.forEach(e=>{t+=String.fromCharCode(e)}),("function"==typeof btoa?btoa(t):Buffer.from(t,"binary").toString("base64")).replace(/\+/g,"-").replace(/\//g,"_").replace(/=+$/,"")}async function r(e){const t=await o().subtle.digest("SHA-256",(new TextEncoder).encode(e));return n(new Uint8Array(t))}Object.defineProperty(t,"__esModule",{value:!0}),t.createPkcePair=t.pkceChallengeFor=void 0,t.pkceChallengeFor=r,t.createPkcePair=async function(){const e=n(o().getRandomValues(new Uint8Array(32)));return{codeVerifier:e,codeChallenge:await r(e)}}},779(e,t,o){var n=this&&this.__createBinding||(Object.create?function(e,t,o,n){void 0===n&&(n=o);var r=Object.getOwnPropertyDescriptor(t,o);r&&!("get"in r?!t.__esModule:r.writable||r.configurable)||(r={enumerable:!0,get:function(){return t[o]}}),Object.defineProperty(e,n,r)}:function(e,t,o,n){void 0===n&&(n=o),e[n]=t[o]}),r=this&&this.__exportStar||function(e,t){for(var o in e)"default"===o||Object.prototype.hasOwnProperty.call(t,o)||n(t,e,o)};Object.defineProperty(t,"__esModule",{value:!0}),r(o(790),t)},790(e,t){Object.defineProperty(t,"__esModule",{value:!0}),t.isBrowser=void 0,t.isBrowser=function(){return"undefined"!=typeof window&&!!window}},160(e,t,o){var n=o(63),r=o(992),s=/^[\x00-\x20\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/,i=/[\n\r\t]/g,a=/^[A-Za-z][A-Za-z0-9+-.]*:\/\//,c=/:\d+$/,l=/^([a-z][a-z0-9.+-]*:)?(\/\/)?([\\/]+)?([\S\s]*)/i,u=/^[a-zA-Z]:/;function p(e){return(e||"").toString().replace(s,"")}var d=[["#","hash"],["?","query"],function(e,t){return g(t.protocol)?e.replace(/\\/g,"/"):e},["/","pathname"],["@","auth",1],[NaN,"host",void 0,1,1],[/:(\d*)$/,"port",void 0,1],[NaN,"hostname",void 0,1,1]],h={hash:1,query:1};function f(e){var t,n=("undefined"!=typeof window?window:void 0!==o.g?o.g:"undefined"!=typeof self?self:{}).location||{},r={},s=typeof(e=e||n);if("blob:"===e.protocol)r=new v(unescape(e.pathname),{});else if("string"===s)for(t in r=new v(e,{}),h)delete r[t];else if("object"===s){for(t in e)t in h||(r[t]=e[t]);void 0===r.slashes&&(r.slashes=a.test(e.href))}return r}function g(e){return"file:"===e||"ftp:"===e||"http:"===e||"https:"===e||"ws:"===e||"wss:"===e}function b(e,t){e=(e=p(e)).replace(i,""),t=t||{};var o,n=l.exec(e),r=n[1]?n[1].toLowerCase():"",s=!!n[2],a=!!n[3],c=0;return s?a?(o=n[2]+n[3]+n[4],c=n[2].length+n[3].length):(o=n[2]+n[4],c=n[2].length):a?(o=n[3]+n[4],c=n[3].length):o=n[4],"file:"===r?c>=2&&(o=o.slice(2)):g(r)?o=n[4]:r?s&&(o=o.slice(2)):c>=2&&g(t.protocol)&&(o=n[4]),{protocol:r,slashes:s||g(r),slashesCount:c,rest:o}}function v(e,t,o){if(e=(e=p(e)).replace(i,""),!(this instanceof v))return new v(e,t,o);var s,a,c,l,h,_,m=d.slice(),w=typeof t,y=this,O=0;for("object"!==w&&"string"!==w&&(o=t,t=null),o&&"function"!=typeof o&&(o=r.parse),s=!(a=b(e||"",t=f(t))).protocol&&!a.slashes,y.slashes=a.slashes||s&&t.slashes,y.protocol=a.protocol||t.protocol||"",e=a.rest,("file:"===a.protocol&&(2!==a.slashesCount||u.test(e))||!a.slashes&&(a.protocol||a.slashesCount<2||!g(y.protocol)))&&(m[3]=[/(.*)/,"pathname"]);O<m.length;O++)"function"!=typeof(l=m[O])?(c=l[0],_=l[1],c!=c?y[_]=e:"string"==typeof c?~(h="@"===c?e.lastIndexOf(c):e.indexOf(c))&&("number"==typeof l[2]?(y[_]=e.slice(0,h),e=e.slice(h+l[2])):(y[_]=e.slice(h),e=e.slice(0,h))):(h=c.exec(e))&&(y[_]=h[1],e=e.slice(0,h.index)),y[_]=y[_]||s&&l[3]&&t[_]||"",l[4]&&(y[_]=y[_].toLowerCase())):e=l(e,y);o&&(y.query=o(y.query)),s&&t.slashes&&"/"!==y.pathname.charAt(0)&&(""!==y.pathname||""!==t.pathname)&&(y.pathname=function(e,t){if(""===e)return t;for(var o=(t||"/").split("/").slice(0,-1).concat(e.split("/")),n=o.length,r=o[n-1],s=!1,i=0;n--;)"."===o[n]?o.splice(n,1):".."===o[n]?(o.splice(n,1),i++):i&&(0===n&&(s=!0),o.splice(n,1),i--);return s&&o.unshift(""),"."!==r&&".."!==r||o.push(""),o.join("/")}(y.pathname,t.pathname)),"/"!==y.pathname.charAt(0)&&g(y.protocol)&&(y.pathname="/"+y.pathname),n(y.port,y.protocol)||(y.host=y.hostname,y.port=""),y.username=y.password="",y.auth&&(~(h=y.auth.indexOf(":"))?(y.username=y.auth.slice(0,h),y.username=encodeURIComponent(decodeURIComponent(y.username)),y.password=y.auth.slice(h+1),y.password=encodeURIComponent(decodeURIComponent(y.password))):y.username=encodeURIComponent(decodeURIComponent(y.auth)),y.auth=y.password?y.username+":"+y.password:y.username),y.origin="file:"!==y.protocol&&g(y.protocol)&&y.host?y.protocol+"//"+y.host:"null",y.href=y.toString()}v.prototype={set:function(e,t,o){var s=this;switch(e){case"query":"string"==typeof t&&t.length&&(t=(o||r.parse)(t)),s[e]=t;break;case"port":s[e]=t,n(t,s.protocol)?t&&(s.host=s.hostname+":"+t):(s.host=s.hostname,s[e]="");break;case"hostname":s[e]=t,s.port&&(t+=":"+s.port),s.host=t;break;case"host":s[e]=t,c.test(t)?(t=t.split(":"),s.port=t.pop(),s.hostname=t.join(":")):(s.hostname=t,s.port="");break;case"protocol":s.protocol=t.toLowerCase(),s.slashes=!o;break;case"pathname":case"hash":if(t){var i="pathname"===e?"/":"#";s[e]=t.charAt(0)!==i?i+t:t}else s[e]=t;break;case"username":case"password":s[e]=encodeURIComponent(t);break;case"auth":var a=t.indexOf(":");~a?(s.username=t.slice(0,a),s.username=encodeURIComponent(decodeURIComponent(s.username)),s.password=t.slice(a+1),s.password=encodeURIComponent(decodeURIComponent(s.password))):s.username=encodeURIComponent(decodeURIComponent(t))}for(var l=0;l<d.length;l++){var u=d[l];u[4]&&(s[u[1]]=s[u[1]].toLowerCase())}return s.auth=s.password?s.username+":"+s.password:s.username,s.origin="file:"!==s.protocol&&g(s.protocol)&&s.host?s.protocol+"//"+s.host:"null",s.href=s.toString(),s},toString:function(e){e&&"function"==typeof e||(e=r.stringify);var t,o=this,n=o.host,s=o.protocol;s&&":"!==s.charAt(s.length-1)&&(s+=":");var i=s+(o.protocol&&o.slashes||g(o.protocol)?"//":"");return o.username?(i+=o.username,o.password&&(i+=":"+o.password),i+="@"):o.password?(i+=":"+o.password,i+="@"):"file:"!==o.protocol&&g(o.protocol)&&!n&&"/"!==o.pathname&&(i+="@"),(":"===n[n.length-1]||c.test(o.hostname)&&!o.port)&&(n+=":"),i+=n+o.pathname,(t="object"==typeof o.query?e(o.query):o.query)&&(i+="?"!==t.charAt(0)?"?"+t:t),o.hash&&(i+=o.hash),i}},v.extractProtocol=b,v.location=f,v.trimLeft=p,v.qs=r,e.exports=v}},t={};function o(n){var r=t[n];if(void 0!==r)return r.exports;var s=t[n]={exports:{}};return e[n].call(s.exports,s,s.exports,o),s.exports}o.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}();var n=o(440);hivesigner=n})();
package/lib/index.d.ts CHANGED
@@ -1,9 +1,11 @@
1
1
  export * from './client';
2
2
  export * from './methods';
3
3
  export * from './factories';
4
+ export * from './pkce';
4
5
  import { Client } from './client';
5
6
  import { Initialize } from './factories';
6
7
  import { sendTransaction, sendOperations, sendOperation, sign } from './methods';
8
+ import { createPkcePair, pkceChallengeFor } from './pkce';
7
9
  declare const _default: {
8
10
  Client: typeof Client;
9
11
  Initialize: typeof Initialize;
@@ -11,5 +13,7 @@ declare const _default: {
11
13
  sendOperations: typeof sendOperations;
12
14
  sendOperation: typeof sendOperation;
13
15
  sign: typeof sign;
16
+ createPkcePair: typeof createPkcePair;
17
+ pkceChallengeFor: typeof pkceChallengeFor;
14
18
  };
15
19
  export default _default;
package/lib/index.js CHANGED
@@ -51,7 +51,12 @@ class Client {
51
51
  this.scope = scope;
52
52
  return this;
53
53
  }
54
- getLoginURL(state, account) {
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 = {}) {
55
60
  const redirectUri = encodeURIComponent(this.callbackURL);
56
61
  let loginURL = `${BASE_URL}/oauth2/authorize?client_id=${this.app}&redirect_uri=${redirectUri}`;
57
62
  if (this.responseType === 'code') {
@@ -66,14 +71,35 @@ class Client {
66
71
  if (account) {
67
72
  loginURL += `&account=${encodeURIComponent(account)}`;
68
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`;
77
+ }
69
78
  return loginURL;
70
79
  }
71
80
  login(options) {
72
81
  if (isBrowser()) {
73
82
  // @ts-ignore
74
- window.location = this.getLoginURL(options.state);
83
+ window.location = this.getLoginURL(options.state, undefined, { codeChallenge: options.codeChallenge });
75
84
  }
76
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
+ }
77
103
  me(cb) {
78
104
  return this.send('me', 'POST', {}, cb);
79
105
  }
@@ -170,18 +196,14 @@ class Client {
170
196
  broadcast(operations, cb) {
171
197
  return this.send('broadcast', 'POST', { operations }, cb);
172
198
  }
173
- async makeRequest(url, method, body) {
199
+ async makeRequest(url, method, body, withToken = true) {
174
200
  if (typeof globalThis.fetch !== 'function') {
175
201
  throw new Error('hivesigner: fetch is not available. Node.js 18+ or a modern browser is required. ' +
176
202
  'If you are in an older environment, provide a global fetch polyfill.');
177
203
  }
178
204
  const response = await globalThis.fetch(url, {
179
205
  method,
180
- headers: {
181
- Accept: 'application/json, text/plain, */*',
182
- 'Content-Type': 'application/json',
183
- Authorization: this.accessToken,
184
- },
206
+ headers: Object.assign({ Accept: 'application/json, text/plain, */*', 'Content-Type': 'application/json' }, (withToken ? { Authorization: this.accessToken } : {})),
185
207
  body: JSON.stringify(body),
186
208
  });
187
209
  const json = await response.json();
@@ -243,18 +265,54 @@ function Initialize(config) {
243
265
  return new Client(config);
244
266
  }
245
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
+
246
300
  var index = {
247
301
  Client,
248
302
  Initialize,
249
303
  sendTransaction,
250
304
  sendOperations,
251
305
  sendOperation,
252
- sign
306
+ sign,
307
+ createPkcePair,
308
+ pkceChallengeFor
253
309
  };
254
310
 
255
311
  exports.Client = Client;
256
312
  exports.Initialize = Initialize;
313
+ exports.createPkcePair = createPkcePair;
257
314
  exports["default"] = index;
315
+ exports.pkceChallengeFor = pkceChallengeFor;
258
316
  exports.sendOperation = sendOperation;
259
317
  exports.sendOperations = sendOperations;
260
318
  exports.sendTransaction = sendTransaction;
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>;
@@ -4,3 +4,4 @@ export * from './callback-function.type';
4
4
  export * from './login-options.interface';
5
5
  export * from './send-response.type';
6
6
  export * from './hive.types';
7
+ export * from './token-response.interface';
@@ -1,3 +1,5 @@
1
1
  export interface LoginOptions {
2
2
  state: string;
3
+ /** From createPkcePair: protects a code flow sign-in with PKCE. */
4
+ codeChallenge?: string;
3
5
  }
@@ -0,0 +1,8 @@
1
+ /** What /api/oauth2/token answers. `refresh_token` is absent for a PKCE
2
+ exchange without a client secret. */
3
+ export interface TokenResponse {
4
+ access_token: string;
5
+ refresh_token?: string;
6
+ expires_in: number;
7
+ username: string;
8
+ }
package/package.json CHANGED
@@ -1,9 +1,12 @@
1
1
  {
2
2
  "name": "hivesigner",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "Hivesigner SDK",
5
5
  "main": "./lib/index",
6
6
  "types": "./lib/index",
7
+ "files": [
8
+ "lib"
9
+ ],
7
10
  "scripts": {
8
11
  "build": "rimraf lib && webpack && rollup -c rollup.config.js && tsc --emitDeclarationOnly",
9
12
  "test": "npx jest",
@@ -1,12 +0,0 @@
1
- {
2
- "permissions": {
3
- "allow": [
4
- "Bash(test:*)",
5
- "WebSearch",
6
- "Bash(npm test:*)",
7
- "Bash(npm run build:*)",
8
- "Bash(npx tsc:*)",
9
- "Bash(yarn build:*)"
10
- ]
11
- }
12
- }
package/.eslintignore DELETED
@@ -1,3 +0,0 @@
1
- node_modules
2
- dist
3
- coverage
package/.eslintrc.js DELETED
@@ -1,16 +0,0 @@
1
- module.exports = {
2
- parser: '@typescript-eslint/parser', // Specifies the ESLint parser
3
- extends: [
4
- 'plugin:@typescript-eslint/recommended' // Uses the recommended rules from @typescript-eslint/eslint-plugin
5
- ],
6
- parserOptions: {
7
- ecmaVersion: 2018, // Allows for the parsing of modern ECMAScript features
8
- sourceType: 'module' // Allows for the use of imports
9
- },
10
- rules: {
11
- // Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
12
- // e.g. '@typescript-eslint/explicit-function-return-type': 'off',
13
- "@typescript-eslint/ban-ts-comment": "off",
14
- "@typescript-eslint/no-empty-function": "off"
15
- }
16
- };
package/CLAUDE.md DELETED
@@ -1,142 +0,0 @@
1
- # CLAUDE.md
2
-
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
-
5
- ## Project Overview
6
-
7
- HiveSigner SDK is a JavaScript/TypeScript SDK for the Hive blockchain's OAuth2 authentication service (HiveSigner). It enables applications to authenticate users and perform Hive blockchain operations on their behalf. The SDK works in both browser and Node.js environments.
8
-
9
- ## Build & Development Commands
10
-
11
- ### Building
12
- ```bash
13
- npm run build
14
- ```
15
- This command:
16
- 1. Cleans the `lib/` directory
17
- 2. Runs webpack to create browser bundle (`lib/hivesigner.min.js`)
18
- 3. Runs rollup to create CommonJS module (`lib/index.js`)
19
- 4. Runs TypeScript compiler to emit type declarations (`lib/**/*.d.ts`)
20
-
21
- ### Testing
22
- ```bash
23
- npm test
24
- ```
25
- Runs all tests using Jest with ts-jest preset.
26
-
27
- To run a single test file:
28
- ```bash
29
- npx jest src/path/to/file.spec.ts
30
- ```
31
-
32
- ### Linting
33
- ```bash
34
- npm run lint
35
- ```
36
- Runs ESLint on all TypeScript files in `src/`.
37
-
38
- ## Architecture
39
-
40
- ### Core Components
41
-
42
- **Client Class (`src/client.ts`)**
43
- - Main entry point for SDK functionality
44
- - Handles OAuth2 authentication flow (login, token management)
45
- - Provides convenience methods for common Hive operations (vote, comment, follow, etc.)
46
- - Uses method overloading to support both callback and Promise-based APIs
47
- - All operations ultimately call `broadcast()` or `send()` methods
48
-
49
- **Dual API Pattern**
50
- The SDK supports both callbacks and Promises throughout. Each public method has overloaded signatures:
51
- ```typescript
52
- public vote(...args): Promise<SendResponse>
53
- public vote(...args, cb: CallbackFunction): Promise<SendResponse>
54
- ```
55
-
56
- ### Directory Structure
57
-
58
- - `src/client.ts` - Main Client class with all SDK methods
59
- - `src/methods/` - Standalone utility methods for operations like `sendOperation`, `sendOperations`, `sign`
60
- - `src/factories/` - Factory functions (mainly deprecated `Initialize` function)
61
- - `src/types/` - TypeScript interfaces and types
62
- - `src/consts/` - Constants for API URLs (API_URL, BASE_URL, BETA_URL)
63
- - `src/utilities/` - Helper utilities like `isBrowser()`
64
-
65
- ### Key Concepts
66
-
67
- **Operation Broadcasting**
68
- - Most methods construct an operation array and call `this.broadcast(operations, cb)`
69
- - `broadcast()` sends operations to HiveSigner API's `/api/broadcast` endpoint
70
- - Operations follow Hive blockchain operation format (from `@hiveio/dhive`)
71
-
72
- **Authentication Flow**
73
- 1. App creates Client instance with `app`, `callbackURL`, and `scope`
74
- 2. User redirects to URL from `getLoginURL()` or calls `login()`
75
- 3. HiveSigner redirects back with `access_token` in query params
76
- 4. App sets token via `setAccessToken(accessToken)`
77
- 5. Authenticated calls include token in Authorization header
78
-
79
- **URI Encoding for Operations**
80
- - `sendOperation()` and `sendOperations()` use `hive-uri` package to encode operations as hive:// URIs
81
- - These URIs are converted to HiveSigner web URLs for browser-based signing
82
-
83
- ## Build Output
84
-
85
- The build produces three main artifacts in `lib/`:
86
- - `index.js` + `index.d.ts` - CommonJS module with TypeScript declarations
87
- - `hivesigner.min.js` - Webpack-bundled browser build (UMD format)
88
- - Directory structure mirrors `src/` for individual module imports
89
-
90
- ## TypeScript Configuration
91
-
92
- - Target: ES5 for broad compatibility
93
- - Module: CommonJS
94
- - Declaration files are generated for all modules
95
- - Test files (`*.spec.ts`) are excluded from compilation
96
-
97
- ## Dependencies
98
-
99
- **Runtime:**
100
- - `cross-fetch` - Isomorphic fetch for Node.js and browser
101
- - `hive-uri` - Encoding/decoding Hive operation URIs
102
- - `@hiveio/dhive` (devDep, used for types) - Hive blockchain library
103
-
104
- **Build:**
105
- - Webpack for browser bundle
106
- - Rollup for CommonJS build
107
- - TypeScript for compilation and type checking
108
- - Jest + ts-jest for testing
109
-
110
- ## Known Issues & Fixes
111
-
112
- ### "Illegal invocation" Error with Fetch
113
- When using the SDK in browser environments, you may encounter:
114
- ```
115
- TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
116
- ```
117
-
118
- **Cause**: The native browser `fetch` function loses its binding to the `window` object when imported and called through `cross-fetch`.
119
-
120
- **Fix Applied**: The fetch function is now explicitly bound at module load time in `src/client.ts`:
121
- ```typescript
122
- const fetch = crossFetch.bind(typeof globalThis !== 'undefined' ? globalThis : undefined)
123
- ```
124
-
125
- This ensures the fetch function maintains proper context in both browser and Node.js environments.
126
-
127
- ### Webpack Build Error with Node.js 17+
128
- When building with Node.js 17+, you may encounter:
129
- ```
130
- Error: error:0308010C:digital envelope routines::unsupported
131
- ```
132
-
133
- **Cause**: Webpack 4 uses the MD4 hash algorithm which was removed in OpenSSL 3.0 (used by Node.js 17+).
134
-
135
- **Fix Applied**: The build script now uses the legacy OpenSSL provider:
136
- ```bash
137
- NODE_OPTIONS=--openssl-legacy-provider webpack
138
- ```
139
-
140
- **Alternative Solutions**:
141
- - Use Node.js 16 or earlier
142
- - Upgrade to Webpack 5 (requires dependency updates)
package/docs/CNAME DELETED
@@ -1 +0,0 @@
1
- demo.hivesigner.com