@redzone/taunt-logins 0.0.8 → 0.0.10

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.
@@ -468,28 +468,68 @@ function ErrorFromResponse(response) {
468
468
  }
469
469
 
470
470
  class TauntApi {
471
- async stdPGET(method, url, body, headers = {}) {
472
- const response = await this.api.request({
471
+ async _api(method, url, body, headers = {}) {
472
+ headers = {
473
+ "Content-Type": "application/json",
474
+ Accept: "application/json",
475
+ ...headers
476
+ };
477
+ if (this.accessToken) {
478
+ headers = {
479
+ ...headers,
480
+ Authorization: `Bearer ${this.accessToken}`
481
+ };
482
+ }
483
+ const response = await this._axios.request({
473
484
  url,
474
485
  method,
475
- headers: {
476
- "Content-Type": "application/json",
477
- Accept: "application/json",
478
- ...headers
479
- },
480
- data: body ? JSON.stringify(body) : null
486
+ headers,
487
+ data: body ? JSON.stringify(body) : null,
488
+ withCredentials: true
481
489
  });
482
490
  const data = response.data;
483
- if (data.refreshToken) {
491
+ if (data?.refreshToken) {
484
492
  this.refreshToken = data.refreshToken;
485
493
  }
494
+ if (data?.accessToken) {
495
+ this.accessToken = data.accessToken;
496
+ }
486
497
  return data;
487
498
  }
488
499
  async post(url, body = {}, headers = {}) {
489
- return this.stdPGET("POST", url, body, headers);
500
+ return this._api("POST", url, body, headers);
490
501
  }
491
502
  async get(url, headers = {}) {
492
- return this.stdPGET("GET", url, undefined, headers);
503
+ return this._api("GET", url, undefined, headers);
504
+ }
505
+ async withProvider(provider, extNonce) {
506
+ const walletAddress = await provider.getAddress();
507
+ if (!walletAddress) {
508
+ throw new Error("No wallet address found");
509
+ }
510
+ const cryptoValuesArray = new Uint32Array(3);
511
+ const clientNonce = crypto.getRandomValues(cryptoValuesArray).toString();
512
+ const serverNonce = await this.nonceLogin(walletAddress, clientNonce);
513
+ const payload = JSON.stringify({
514
+ clientNonce,
515
+ serverNonce
516
+ });
517
+ const message = `Sign this message with your wallet to connect to Taunt Battleworld ::: ${payload}`;
518
+ let signature;
519
+ try {
520
+ signature = await provider.personalSign(message, walletAddress);
521
+ } catch (err) {
522
+ throw new Error("User denied message signature");
523
+ }
524
+ if (!signature) {
525
+ throw new Error("No signature returned");
526
+ }
527
+ return this.loginExtWithWeb3WalletSignature({
528
+ walletAddress,
529
+ message,
530
+ signature,
531
+ extNonce
532
+ });
493
533
  }
494
534
  // this.user = data
495
535
  // localStorage.setItem("user", JSON.stringify(data))
@@ -599,15 +639,16 @@ class TauntApi {
599
639
  }
600
640
  constructor(endpoint){
601
641
  this.refreshToken = null;
642
+ this.accessToken = null;
602
643
  this.claimrToken = null;
603
644
  this.onError = async (error)=>{
604
645
  const originalRequest = error.config;
605
- if (error.response.status === 401 && !originalRequest._retry) {
646
+ if (error.response.status === 401 && !originalRequest._retry && this.refreshToken) {
606
647
  originalRequest._retry = true;
607
648
  console.log("401 - refreshing token");
608
649
  try {
609
650
  const data = await this.refresh();
610
- return this.api(originalRequest);
651
+ return this._axios(originalRequest);
611
652
  } catch (error) {
612
653
  console.log("Unable to refresh access token, please log in");
613
654
  this.refreshToken = null;
@@ -621,41 +662,48 @@ class TauntApi {
621
662
  walletAddress,
622
663
  clientNonce
623
664
  });
624
- this.loginWithMagicDid = (did)=>this.post("/v1/auth/login/did", {
625
- did
626
- });
665
+ // loginWithMagicDid = (did: string) => this.post("/v1/auth/login/did", { did })
627
666
  this.loginWithWeb3WalletSignature = (props)=>this.post("/v1/auth/login/signature", props);
628
- this.loginExtWithWeb3WalletSignature = (props)=>this.post("/v1/auth/login/ext-signature", props);
629
- this.refresh = (refreshToken)=>this.post(`/v1/auth/token/refresh`, {
630
- token: refreshToken || this.refreshToken
667
+ this.loginExtWithWeb3WalletSignature = (props)=>{
668
+ props.extNonce = props.extNonce || this.randomTokenString();
669
+ return this.post("/v1/auth/login/ext-signature", props);
670
+ };
671
+ this.refresh = (refreshToken)=>{
672
+ const token = refreshToken || this.refreshToken;
673
+ if (!token) {
674
+ return Promise.reject(new Error("No refresh token available"));
675
+ }
676
+ return this.post(`/v1/auth/token/refresh`, {
677
+ token
631
678
  });
679
+ };
632
680
  // Logout of the backend with access token. Assumes user is currently logged in and has a cookie with the access token
633
681
  this.logout = async ()=>{
634
682
  // If logging out fails on the backend we'll still remove the user info
635
- await this.api.post("/v1/auth/logout");
683
+ await this.post("/v1/auth/logout");
636
684
  await this.writePlayerEvent("player_logged_out");
637
685
  };
638
686
  this.getClaimrToken = async ()=>{
639
687
  if (!this.claimrToken) {
640
688
  const url = "v1/claimr/token";
641
- const { data } = await this.api.get(`${url}`);
689
+ const data = await this.get(`${url}`);
642
690
  this.claimrToken = data.data.token;
643
691
  }
644
692
  return this.claimrToken;
645
693
  };
646
694
  this.getClaimrData = async ()=>{
647
- const { data } = await this.api.get("/v1/beamable/inventory/skulls");
695
+ const data = await this.get("/v1/beamable/inventory/skulls");
648
696
  return data;
649
697
  };
698
+ this.randomTokenString = ()=>crypto.randomUUID().replace(/-/g, "");
650
699
  // Use the cookie stored in the browser to get the user and save user model in state and local storage
651
700
  // This assumes that the user is logged to backend in and has a cookie jwt
652
- this.getLoggedInUser = ()=>this.api.get("/v1/auth/me");
653
- this.api = axios__default.default.create({
654
- baseURL: `${endpoint}`,
655
- withCredentials: true
701
+ this.getLoggedInUser = ()=>this.get("/v1/auth/me");
702
+ this._axios = axios__default.default.create({
703
+ baseURL: `${endpoint}`
656
704
  });
657
705
  // Response interceptor for API calls
658
- this.api.interceptors.response.use((response)=>response, (error)=>this.onError(error));
706
+ this._axios.interceptors.response.use((response)=>response, (error)=>this.onError(error));
659
707
  }
660
708
  }
661
709
 
@@ -669,102 +717,67 @@ const getMagic = (magicKey)=>new magicSdk.Magic(magicKey, {
669
717
  new oauth2.OAuthExtension()
670
718
  ]
671
719
  });
672
- function emailOTPWithMagic(magicKey, email) {
673
- const magic = getMagic(magicKey);
720
+ function emailOTPWithMagic(magicKey, email, magic) {
721
+ magic = magic || getMagic(magicKey);
674
722
  return magic.auth.loginWithEmailOTP({
675
723
  email
676
724
  });
677
725
  }
678
- function telegramWithMagic(magicKey) {
679
- const magic = getMagic(magicKey);
726
+ function telegramWithMagic(magicKey, magic) {
727
+ magic = magic || getMagic(magicKey);
680
728
  return magic.oauth2.loginWithPopup({
681
729
  provider: "telegram"
682
730
  });
683
731
  }
684
- async function tauntMagicTelegramLogin(tauntServiceEndpoint, magicKey, tauntApi) {
685
- const taunt = tauntApi || new TauntApi(tauntServiceEndpoint);
686
- try {
687
- let result = await telegramWithMagic(magicKey);
688
- const errResult = result;
689
- if (errResult.error) {
690
- throw new Error(`No ID token returned ${errResult.error}`);
691
- }
692
- result = result;
693
- console.log("Magic telegram login", {
694
- result
695
- });
696
- return taunt.loginWithMagicDid(result.magic.idToken);
697
- } catch (err) {
698
- console.error("Magic login error:", err);
699
- throw err;
700
- }
732
+ function tauntMagicTelegramLogin(tauntServiceEndpoint, magicKey, tauntApi, extNonce) {
733
+ return withLoginTry(tauntServiceEndpoint, tauntApi, magicKey, undefined, extNonce, (magic)=>telegramWithMagic(magicKey, magic));
701
734
  }
702
- async function tauntMagicEmailOTPLogin(tauntServiceEndpoint, magicKey, email, tauntApi) {
703
- const taunt = tauntApi || new TauntApi(tauntServiceEndpoint);
735
+ function tauntMagicEmailOTPLogin(tauntServiceEndpoint, magicKey, email, tauntApi, extNonce) {
736
+ return withLoginTry(tauntServiceEndpoint, tauntApi, magicKey, undefined, extNonce, (magic)=>emailOTPWithMagic(magicKey, email, magic));
737
+ }
738
+ async function withLoginTry(endpoint, tauntApi, magicKey, magic, extNonce, fn) {
739
+ tauntApi = tauntApi || new TauntApi(endpoint);
740
+ magic = magic || getMagic(magicKey);
704
741
  try {
705
- const did = await emailOTPWithMagic(magicKey, email);
706
- if (!did) throw new Error("No DID returned");
707
- console.log("Magic email OTP login", {
708
- did
709
- });
710
- return taunt.loginWithMagicDid(did);
742
+ if (!await magic.user.isLoggedIn()) {
743
+ await fn(magic, tauntApi);
744
+ }
745
+ // check if user is logged in
746
+ const isLoggedIn = await magic.user.isLoggedIn();
747
+ if (!isLoggedIn) {
748
+ throw new Error("User is not logged in");
749
+ }
750
+ return tauntApi.withProvider({
751
+ getAddress: ()=>magic.rpcProvider.send("eth_accounts", []).then((accounts)=>accounts[0]),
752
+ personalSign: (message, address)=>magic.rpcProvider.send("personal_sign", [
753
+ message,
754
+ address
755
+ ]).then((sig)=>sig)
756
+ }, extNonce);
711
757
  } catch (err) {
712
758
  console.error("Magic login error:", err);
713
759
  throw err;
714
760
  }
715
761
  }
716
- async function tauntMagicDidLogin(tauntServiceEndpoint, did, tauntApi) {
717
- const taunt = tauntApi || new TauntApi(tauntServiceEndpoint);
718
- return taunt.loginWithMagicDid(did);
719
- }
720
762
 
721
- async function tauntSignWithMetamask(tauntServiceEndpoint, provider, tauntApi) {
763
+ async function tauntMetamaskLogin(tauntServiceEndpoint, provider, tauntApi, extNonce) {
722
764
  provider = provider || window.ethereum;
723
- if (!provider) throw new Error("MetaMask provider not found");
724
- const accounts = await provider.request({
725
- method: "eth_requestAccounts"
726
- });
727
- if (!accounts.length) throw new Error("No accounts returned");
728
- console.log("MetaMask", {
729
- accounts
730
- });
731
- const walletAddress = accounts[0];
732
- const cryptoValuesArray = new Uint32Array(3);
733
- const clientNonce = crypto.getRandomValues(cryptoValuesArray).toString();
734
- const taunt = tauntApi || new TauntApi(tauntServiceEndpoint);
735
- const serverNonce = await taunt.nonceLogin(walletAddress, clientNonce);
736
- const payload = JSON.stringify({
737
- clientNonce,
738
- serverNonce
739
- });
740
- const message = `Sign this message with your wallet to connect to Taunt Battleworld ::: ${payload}`;
741
- let signature;
742
- try {
743
- signature = await provider.request({
744
- method: "personal_sign",
745
- params: [
746
- message,
747
- walletAddress
748
- ]
749
- });
750
- } catch (err) {
751
- throw new Error("User denied message signature");
765
+ if (!provider) {
766
+ throw new Error("MetaMask provider not found");
752
767
  }
753
- if (!signature) throw new Error("No signature returned");
754
- return {
755
- walletAddress,
756
- message,
757
- signature
758
- };
759
- }
760
- async function tauntMetamaskLogin(tauntServiceEndpoint, providerParam, tauntApi) {
761
768
  const taunt = tauntApi || new TauntApi(tauntServiceEndpoint);
762
- const { walletAddress, message, signature } = await tauntSignWithMetamask(tauntServiceEndpoint, providerParam, tauntApi);
763
- return taunt.loginWithWeb3WalletSignature({
764
- walletAddress,
765
- message,
766
- signature
767
- });
769
+ return taunt.withProvider({
770
+ getAddress: ()=>provider.request({
771
+ method: "eth_requestAccounts"
772
+ }).then((accounts)=>accounts?.[0]),
773
+ personalSign: (message, address)=>provider.request({
774
+ method: "personal_sign",
775
+ params: [
776
+ message,
777
+ address
778
+ ]
779
+ })
780
+ }, extNonce);
768
781
  }
769
782
 
770
783
  exports.BadGatewayError = BadGatewayError;
@@ -810,9 +823,7 @@ exports.UnsupportedMediaTypeError = UnsupportedMediaTypeError;
810
823
  exports.UpgradeRequiredError = UpgradeRequiredError;
811
824
  exports.VariantAlsoNegotiatesError = VariantAlsoNegotiatesError;
812
825
  exports.emailOTPWithMagic = emailOTPWithMagic;
813
- exports.tauntMagicDidLogin = tauntMagicDidLogin;
814
826
  exports.tauntMagicEmailOTPLogin = tauntMagicEmailOTPLogin;
815
827
  exports.tauntMagicTelegramLogin = tauntMagicTelegramLogin;
816
828
  exports.tauntMetamaskLogin = tauntMetamaskLogin;
817
- exports.tauntSignWithMetamask = tauntSignWithMetamask;
818
829
  exports.telegramWithMagic = telegramWithMagic;
@@ -1,6 +1,8 @@
1
- import { AxiosResponse, AxiosRequestConfig, Method } from 'axios';
1
+ import { AxiosResponse, AxiosRequestConfig } from 'axios';
2
+ import * as _magic_ext_oauth2 from '@magic-ext/oauth2';
3
+ import { OAuthExtension } from '@magic-ext/oauth2';
2
4
  import * as magic_sdk from 'magic-sdk';
3
- import { OAuthRedirectResult, OAuthRedirectError } from '@magic-ext/oauth2';
5
+ import * as _magic_sdk_provider from '@magic-sdk/provider';
4
6
  import { BaseProvider } from '@metamask/providers';
5
7
 
6
8
  declare class ErrorResponse {
@@ -291,7 +293,7 @@ type TauntSigProps = {
291
293
  signature: string;
292
294
  };
293
295
  type TauntExtSigProps = TauntSigProps & {
294
- extNonce: string;
296
+ extNonce?: string;
295
297
  };
296
298
  type TauntRespType = {
297
299
  accessToken: string;
@@ -313,8 +315,9 @@ type ClaimrCampaignData = {
313
315
  questComplete: boolean;
314
316
  };
315
317
  declare class TauntApi {
316
- private api;
318
+ private _axios;
317
319
  private refreshToken;
320
+ private accessToken;
318
321
  private claimrToken;
319
322
  constructor(endpoint: string);
320
323
  onError: (error: {
@@ -323,22 +326,28 @@ declare class TauntApi {
323
326
  };
324
327
  response: AxiosResponse;
325
328
  }) => Promise<AxiosResponse<any, any, {}>>;
326
- stdPGET<T = TauntRespType>(method: Method, url: string, body?: unknown, headers?: {}): Promise<T>;
329
+ private _api;
327
330
  post<T = TauntRespType>(url: string, body?: {}, headers?: {}): Promise<T>;
328
331
  get<T = TauntRespType>(url: string, headers?: {}): Promise<T>;
329
332
  nonceLogin: (walletAddress: string, clientNonce: string) => Promise<string>;
330
- loginWithMagicDid: (did: string) => Promise<TauntRespType>;
331
333
  loginWithWeb3WalletSignature: (props: TauntSigProps) => Promise<TauntRespType>;
332
334
  loginExtWithWeb3WalletSignature: (props: TauntExtSigProps) => Promise<TauntRespType>;
333
335
  refresh: (refreshToken?: string) => Promise<TauntRespType>;
334
336
  logout: () => Promise<void>;
335
- getClaimrToken: () => Promise<string | null>;
337
+ getClaimrToken: () => Promise<string>;
336
338
  getClaimrData: () => Promise<ClaimrCampaignData>;
337
- getLoggedInUser: () => Promise<AxiosResponse<TauntUser, any, {}>>;
339
+ randomTokenString: () => string;
340
+ withProvider(provider: {
341
+ getAddress: () => Promise<string | undefined | null>;
342
+ personalSign: (message: string, address: string) => Promise<string | undefined | null>;
343
+ }, extNonce?: string): Promise<TauntRespType>;
344
+ getLoggedInUser: () => Promise<TauntUser>;
338
345
  writePlayerEvent(eventName: string, eventData?: unknown, retryIfLoginNeeded?: boolean): Promise<void>;
339
346
  }
340
347
 
341
- declare function emailOTPWithMagic(magicKey: string, email: string): magic_sdk.PromiEvent<string | null, {
348
+ declare const getMagic: (magicKey: string) => _magic_sdk_provider.InstanceWithExtensions<_magic_sdk_provider.SDKBase, OAuthExtension[]>;
349
+ type MagicType = ReturnType<typeof getMagic>;
350
+ declare function emailOTPWithMagic(magicKey: string, email: string, magic?: MagicType): magic_sdk.PromiEvent<string | null, {
342
351
  "email-otp-sent": () => void;
343
352
  "login-throttled": () => void;
344
353
  "invalid-email-otp": () => void;
@@ -367,23 +376,18 @@ declare function emailOTPWithMagic(magicKey: string, email: string): magic_sdk.P
367
376
  settled: () => void;
368
377
  "closed-by-user": () => void;
369
378
  }>;
370
- declare function telegramWithMagic(magicKey: string): magic_sdk.PromiEvent<OAuthRedirectResult | OAuthRedirectError, {
371
- done: (result: OAuthRedirectResult | OAuthRedirectError) => void;
379
+ declare function telegramWithMagic(magicKey: string, magic?: MagicType): magic_sdk.PromiEvent<_magic_ext_oauth2.OAuthRedirectResult | _magic_ext_oauth2.OAuthRedirectError, {
380
+ done: (result: _magic_ext_oauth2.OAuthRedirectResult | _magic_ext_oauth2.OAuthRedirectError) => void;
372
381
  error: (reason: any) => void;
373
382
  settled: () => void;
374
383
  "closed-by-user": () => void;
375
384
  }>;
376
- declare function tauntMagicTelegramLogin(tauntServiceEndpoint: string, magicKey: string, tauntApi?: TauntApi): Promise<{
385
+ declare function tauntMagicTelegramLogin(tauntServiceEndpoint: string, magicKey: string, tauntApi?: TauntApi, extNonce?: string): Promise<{
377
386
  accessToken: string;
378
387
  refreshToken: string;
379
388
  isNewUser: string;
380
389
  }>;
381
- declare function tauntMagicEmailOTPLogin(tauntServiceEndpoint: string, magicKey: string, email: string, tauntApi?: TauntApi): Promise<{
382
- accessToken: string;
383
- refreshToken: string;
384
- isNewUser: string;
385
- }>;
386
- declare function tauntMagicDidLogin(tauntServiceEndpoint: string, did: string, tauntApi?: TauntApi): Promise<{
390
+ declare function tauntMagicEmailOTPLogin(tauntServiceEndpoint: string, magicKey: string, email: string, tauntApi?: TauntApi, extNonce?: string): Promise<{
387
391
  accessToken: string;
388
392
  refreshToken: string;
389
393
  isNewUser: string;
@@ -394,16 +398,11 @@ declare global {
394
398
  ethereum?: BaseProvider;
395
399
  }
396
400
  }
397
- declare function tauntSignWithMetamask(tauntServiceEndpoint: string, provider?: BaseProvider, tauntApi?: TauntApi): Promise<{
398
- walletAddress: string;
399
- message: string;
400
- signature: string;
401
- }>;
402
- declare function tauntMetamaskLogin(tauntServiceEndpoint: string, providerParam?: BaseProvider, tauntApi?: TauntApi): Promise<{
401
+ declare function tauntMetamaskLogin(tauntServiceEndpoint: string, provider?: BaseProvider, tauntApi?: TauntApi, extNonce?: string): Promise<{
403
402
  accessToken: string;
404
403
  refreshToken: string;
405
404
  isNewUser: string;
406
405
  }>;
407
406
 
408
- export { BadGatewayError, BadRequestError, BandwidthLimitExceededError, ConflictError, ErrorFromResponse, ErrorResponse, ExpectationFailedError, FailedDependencyError, ForbiddenError, GatewayTimeoutError, GoneError, HTTPVersionNotSupportedError, ImATeapotError, InsufficientStorageError, InternalServerError, LengthRequiredError, LockedError, LoopDetectedError, MethodNotAllowedError, NetworkAuthenticationRequiredError, NotAcceptableError, NotExtendedError, NotFoundError, NotImplementedError, PaymentRequiredError, PreconditionFailedError, PreconditionRequiredError, ProxyAuthenticationRequiredError, RequestEntityTooLargeError, RequestHeaderFieldsTooLargeError, RequestTimeoutError, RequestUriTooLongError, RequestedRangeNotSatisfiableError, ServiceUnavailableError, TauntApi, TooManyRequestsError, UnauthorizedError, UnknownError, UnprocessableEntityError, UnsupportedMediaTypeError, UpgradeRequiredError, VariantAlsoNegotiatesError, emailOTPWithMagic, tauntMagicDidLogin, tauntMagicEmailOTPLogin, tauntMagicTelegramLogin, tauntMetamaskLogin, tauntSignWithMetamask, telegramWithMagic };
407
+ export { BadGatewayError, BadRequestError, BandwidthLimitExceededError, ConflictError, ErrorFromResponse, ErrorResponse, ExpectationFailedError, FailedDependencyError, ForbiddenError, GatewayTimeoutError, GoneError, HTTPVersionNotSupportedError, ImATeapotError, InsufficientStorageError, InternalServerError, LengthRequiredError, LockedError, LoopDetectedError, MethodNotAllowedError, NetworkAuthenticationRequiredError, NotAcceptableError, NotExtendedError, NotFoundError, NotImplementedError, PaymentRequiredError, PreconditionFailedError, PreconditionRequiredError, ProxyAuthenticationRequiredError, RequestEntityTooLargeError, RequestHeaderFieldsTooLargeError, RequestTimeoutError, RequestUriTooLongError, RequestedRangeNotSatisfiableError, ServiceUnavailableError, TauntApi, TooManyRequestsError, UnauthorizedError, UnknownError, UnprocessableEntityError, UnsupportedMediaTypeError, UpgradeRequiredError, VariantAlsoNegotiatesError, emailOTPWithMagic, tauntMagicEmailOTPLogin, tauntMagicTelegramLogin, tauntMetamaskLogin, telegramWithMagic };
409
408
  export type { ClaimrCampaignData, TauntExtSigProps, TauntSigProps, TauntUser };
@@ -1,6 +1,8 @@
1
- import { AxiosResponse, AxiosRequestConfig, Method } from 'axios';
1
+ import { AxiosResponse, AxiosRequestConfig } from 'axios';
2
+ import * as _magic_ext_oauth2 from '@magic-ext/oauth2';
3
+ import { OAuthExtension } from '@magic-ext/oauth2';
2
4
  import * as magic_sdk from 'magic-sdk';
3
- import { OAuthRedirectResult, OAuthRedirectError } from '@magic-ext/oauth2';
5
+ import * as _magic_sdk_provider from '@magic-sdk/provider';
4
6
  import { BaseProvider } from '@metamask/providers';
5
7
 
6
8
  declare class ErrorResponse {
@@ -291,7 +293,7 @@ type TauntSigProps = {
291
293
  signature: string;
292
294
  };
293
295
  type TauntExtSigProps = TauntSigProps & {
294
- extNonce: string;
296
+ extNonce?: string;
295
297
  };
296
298
  type TauntRespType = {
297
299
  accessToken: string;
@@ -313,8 +315,9 @@ type ClaimrCampaignData = {
313
315
  questComplete: boolean;
314
316
  };
315
317
  declare class TauntApi {
316
- private api;
318
+ private _axios;
317
319
  private refreshToken;
320
+ private accessToken;
318
321
  private claimrToken;
319
322
  constructor(endpoint: string);
320
323
  onError: (error: {
@@ -323,22 +326,28 @@ declare class TauntApi {
323
326
  };
324
327
  response: AxiosResponse;
325
328
  }) => Promise<AxiosResponse<any, any, {}>>;
326
- stdPGET<T = TauntRespType>(method: Method, url: string, body?: unknown, headers?: {}): Promise<T>;
329
+ private _api;
327
330
  post<T = TauntRespType>(url: string, body?: {}, headers?: {}): Promise<T>;
328
331
  get<T = TauntRespType>(url: string, headers?: {}): Promise<T>;
329
332
  nonceLogin: (walletAddress: string, clientNonce: string) => Promise<string>;
330
- loginWithMagicDid: (did: string) => Promise<TauntRespType>;
331
333
  loginWithWeb3WalletSignature: (props: TauntSigProps) => Promise<TauntRespType>;
332
334
  loginExtWithWeb3WalletSignature: (props: TauntExtSigProps) => Promise<TauntRespType>;
333
335
  refresh: (refreshToken?: string) => Promise<TauntRespType>;
334
336
  logout: () => Promise<void>;
335
- getClaimrToken: () => Promise<string | null>;
337
+ getClaimrToken: () => Promise<string>;
336
338
  getClaimrData: () => Promise<ClaimrCampaignData>;
337
- getLoggedInUser: () => Promise<AxiosResponse<TauntUser, any, {}>>;
339
+ randomTokenString: () => string;
340
+ withProvider(provider: {
341
+ getAddress: () => Promise<string | undefined | null>;
342
+ personalSign: (message: string, address: string) => Promise<string | undefined | null>;
343
+ }, extNonce?: string): Promise<TauntRespType>;
344
+ getLoggedInUser: () => Promise<TauntUser>;
338
345
  writePlayerEvent(eventName: string, eventData?: unknown, retryIfLoginNeeded?: boolean): Promise<void>;
339
346
  }
340
347
 
341
- declare function emailOTPWithMagic(magicKey: string, email: string): magic_sdk.PromiEvent<string | null, {
348
+ declare const getMagic: (magicKey: string) => _magic_sdk_provider.InstanceWithExtensions<_magic_sdk_provider.SDKBase, OAuthExtension[]>;
349
+ type MagicType = ReturnType<typeof getMagic>;
350
+ declare function emailOTPWithMagic(magicKey: string, email: string, magic?: MagicType): magic_sdk.PromiEvent<string | null, {
342
351
  "email-otp-sent": () => void;
343
352
  "login-throttled": () => void;
344
353
  "invalid-email-otp": () => void;
@@ -367,23 +376,18 @@ declare function emailOTPWithMagic(magicKey: string, email: string): magic_sdk.P
367
376
  settled: () => void;
368
377
  "closed-by-user": () => void;
369
378
  }>;
370
- declare function telegramWithMagic(magicKey: string): magic_sdk.PromiEvent<OAuthRedirectResult | OAuthRedirectError, {
371
- done: (result: OAuthRedirectResult | OAuthRedirectError) => void;
379
+ declare function telegramWithMagic(magicKey: string, magic?: MagicType): magic_sdk.PromiEvent<_magic_ext_oauth2.OAuthRedirectResult | _magic_ext_oauth2.OAuthRedirectError, {
380
+ done: (result: _magic_ext_oauth2.OAuthRedirectResult | _magic_ext_oauth2.OAuthRedirectError) => void;
372
381
  error: (reason: any) => void;
373
382
  settled: () => void;
374
383
  "closed-by-user": () => void;
375
384
  }>;
376
- declare function tauntMagicTelegramLogin(tauntServiceEndpoint: string, magicKey: string, tauntApi?: TauntApi): Promise<{
385
+ declare function tauntMagicTelegramLogin(tauntServiceEndpoint: string, magicKey: string, tauntApi?: TauntApi, extNonce?: string): Promise<{
377
386
  accessToken: string;
378
387
  refreshToken: string;
379
388
  isNewUser: string;
380
389
  }>;
381
- declare function tauntMagicEmailOTPLogin(tauntServiceEndpoint: string, magicKey: string, email: string, tauntApi?: TauntApi): Promise<{
382
- accessToken: string;
383
- refreshToken: string;
384
- isNewUser: string;
385
- }>;
386
- declare function tauntMagicDidLogin(tauntServiceEndpoint: string, did: string, tauntApi?: TauntApi): Promise<{
390
+ declare function tauntMagicEmailOTPLogin(tauntServiceEndpoint: string, magicKey: string, email: string, tauntApi?: TauntApi, extNonce?: string): Promise<{
387
391
  accessToken: string;
388
392
  refreshToken: string;
389
393
  isNewUser: string;
@@ -394,16 +398,11 @@ declare global {
394
398
  ethereum?: BaseProvider;
395
399
  }
396
400
  }
397
- declare function tauntSignWithMetamask(tauntServiceEndpoint: string, provider?: BaseProvider, tauntApi?: TauntApi): Promise<{
398
- walletAddress: string;
399
- message: string;
400
- signature: string;
401
- }>;
402
- declare function tauntMetamaskLogin(tauntServiceEndpoint: string, providerParam?: BaseProvider, tauntApi?: TauntApi): Promise<{
401
+ declare function tauntMetamaskLogin(tauntServiceEndpoint: string, provider?: BaseProvider, tauntApi?: TauntApi, extNonce?: string): Promise<{
403
402
  accessToken: string;
404
403
  refreshToken: string;
405
404
  isNewUser: string;
406
405
  }>;
407
406
 
408
- export { BadGatewayError, BadRequestError, BandwidthLimitExceededError, ConflictError, ErrorFromResponse, ErrorResponse, ExpectationFailedError, FailedDependencyError, ForbiddenError, GatewayTimeoutError, GoneError, HTTPVersionNotSupportedError, ImATeapotError, InsufficientStorageError, InternalServerError, LengthRequiredError, LockedError, LoopDetectedError, MethodNotAllowedError, NetworkAuthenticationRequiredError, NotAcceptableError, NotExtendedError, NotFoundError, NotImplementedError, PaymentRequiredError, PreconditionFailedError, PreconditionRequiredError, ProxyAuthenticationRequiredError, RequestEntityTooLargeError, RequestHeaderFieldsTooLargeError, RequestTimeoutError, RequestUriTooLongError, RequestedRangeNotSatisfiableError, ServiceUnavailableError, TauntApi, TooManyRequestsError, UnauthorizedError, UnknownError, UnprocessableEntityError, UnsupportedMediaTypeError, UpgradeRequiredError, VariantAlsoNegotiatesError, emailOTPWithMagic, tauntMagicDidLogin, tauntMagicEmailOTPLogin, tauntMagicTelegramLogin, tauntMetamaskLogin, tauntSignWithMetamask, telegramWithMagic };
407
+ export { BadGatewayError, BadRequestError, BandwidthLimitExceededError, ConflictError, ErrorFromResponse, ErrorResponse, ExpectationFailedError, FailedDependencyError, ForbiddenError, GatewayTimeoutError, GoneError, HTTPVersionNotSupportedError, ImATeapotError, InsufficientStorageError, InternalServerError, LengthRequiredError, LockedError, LoopDetectedError, MethodNotAllowedError, NetworkAuthenticationRequiredError, NotAcceptableError, NotExtendedError, NotFoundError, NotImplementedError, PaymentRequiredError, PreconditionFailedError, PreconditionRequiredError, ProxyAuthenticationRequiredError, RequestEntityTooLargeError, RequestHeaderFieldsTooLargeError, RequestTimeoutError, RequestUriTooLongError, RequestedRangeNotSatisfiableError, ServiceUnavailableError, TauntApi, TooManyRequestsError, UnauthorizedError, UnknownError, UnprocessableEntityError, UnsupportedMediaTypeError, UpgradeRequiredError, VariantAlsoNegotiatesError, emailOTPWithMagic, tauntMagicEmailOTPLogin, tauntMagicTelegramLogin, tauntMetamaskLogin, telegramWithMagic };
409
408
  export type { ClaimrCampaignData, TauntExtSigProps, TauntSigProps, TauntUser };
package/dist/es/index.js CHANGED
@@ -462,28 +462,68 @@ function ErrorFromResponse(response) {
462
462
  }
463
463
 
464
464
  class TauntApi {
465
- async stdPGET(method, url, body, headers = {}) {
466
- const response = await this.api.request({
465
+ async _api(method, url, body, headers = {}) {
466
+ headers = {
467
+ "Content-Type": "application/json",
468
+ Accept: "application/json",
469
+ ...headers
470
+ };
471
+ if (this.accessToken) {
472
+ headers = {
473
+ ...headers,
474
+ Authorization: `Bearer ${this.accessToken}`
475
+ };
476
+ }
477
+ const response = await this._axios.request({
467
478
  url,
468
479
  method,
469
- headers: {
470
- "Content-Type": "application/json",
471
- Accept: "application/json",
472
- ...headers
473
- },
474
- data: body ? JSON.stringify(body) : null
480
+ headers,
481
+ data: body ? JSON.stringify(body) : null,
482
+ withCredentials: true
475
483
  });
476
484
  const data = response.data;
477
- if (data.refreshToken) {
485
+ if (data?.refreshToken) {
478
486
  this.refreshToken = data.refreshToken;
479
487
  }
488
+ if (data?.accessToken) {
489
+ this.accessToken = data.accessToken;
490
+ }
480
491
  return data;
481
492
  }
482
493
  async post(url, body = {}, headers = {}) {
483
- return this.stdPGET("POST", url, body, headers);
494
+ return this._api("POST", url, body, headers);
484
495
  }
485
496
  async get(url, headers = {}) {
486
- return this.stdPGET("GET", url, undefined, headers);
497
+ return this._api("GET", url, undefined, headers);
498
+ }
499
+ async withProvider(provider, extNonce) {
500
+ const walletAddress = await provider.getAddress();
501
+ if (!walletAddress) {
502
+ throw new Error("No wallet address found");
503
+ }
504
+ const cryptoValuesArray = new Uint32Array(3);
505
+ const clientNonce = crypto.getRandomValues(cryptoValuesArray).toString();
506
+ const serverNonce = await this.nonceLogin(walletAddress, clientNonce);
507
+ const payload = JSON.stringify({
508
+ clientNonce,
509
+ serverNonce
510
+ });
511
+ const message = `Sign this message with your wallet to connect to Taunt Battleworld ::: ${payload}`;
512
+ let signature;
513
+ try {
514
+ signature = await provider.personalSign(message, walletAddress);
515
+ } catch (err) {
516
+ throw new Error("User denied message signature");
517
+ }
518
+ if (!signature) {
519
+ throw new Error("No signature returned");
520
+ }
521
+ return this.loginExtWithWeb3WalletSignature({
522
+ walletAddress,
523
+ message,
524
+ signature,
525
+ extNonce
526
+ });
487
527
  }
488
528
  // this.user = data
489
529
  // localStorage.setItem("user", JSON.stringify(data))
@@ -593,15 +633,16 @@ class TauntApi {
593
633
  }
594
634
  constructor(endpoint){
595
635
  this.refreshToken = null;
636
+ this.accessToken = null;
596
637
  this.claimrToken = null;
597
638
  this.onError = async (error)=>{
598
639
  const originalRequest = error.config;
599
- if (error.response.status === 401 && !originalRequest._retry) {
640
+ if (error.response.status === 401 && !originalRequest._retry && this.refreshToken) {
600
641
  originalRequest._retry = true;
601
642
  console.log("401 - refreshing token");
602
643
  try {
603
644
  const data = await this.refresh();
604
- return this.api(originalRequest);
645
+ return this._axios(originalRequest);
605
646
  } catch (error) {
606
647
  console.log("Unable to refresh access token, please log in");
607
648
  this.refreshToken = null;
@@ -615,41 +656,48 @@ class TauntApi {
615
656
  walletAddress,
616
657
  clientNonce
617
658
  });
618
- this.loginWithMagicDid = (did)=>this.post("/v1/auth/login/did", {
619
- did
620
- });
659
+ // loginWithMagicDid = (did: string) => this.post("/v1/auth/login/did", { did })
621
660
  this.loginWithWeb3WalletSignature = (props)=>this.post("/v1/auth/login/signature", props);
622
- this.loginExtWithWeb3WalletSignature = (props)=>this.post("/v1/auth/login/ext-signature", props);
623
- this.refresh = (refreshToken)=>this.post(`/v1/auth/token/refresh`, {
624
- token: refreshToken || this.refreshToken
661
+ this.loginExtWithWeb3WalletSignature = (props)=>{
662
+ props.extNonce = props.extNonce || this.randomTokenString();
663
+ return this.post("/v1/auth/login/ext-signature", props);
664
+ };
665
+ this.refresh = (refreshToken)=>{
666
+ const token = refreshToken || this.refreshToken;
667
+ if (!token) {
668
+ return Promise.reject(new Error("No refresh token available"));
669
+ }
670
+ return this.post(`/v1/auth/token/refresh`, {
671
+ token
625
672
  });
673
+ };
626
674
  // Logout of the backend with access token. Assumes user is currently logged in and has a cookie with the access token
627
675
  this.logout = async ()=>{
628
676
  // If logging out fails on the backend we'll still remove the user info
629
- await this.api.post("/v1/auth/logout");
677
+ await this.post("/v1/auth/logout");
630
678
  await this.writePlayerEvent("player_logged_out");
631
679
  };
632
680
  this.getClaimrToken = async ()=>{
633
681
  if (!this.claimrToken) {
634
682
  const url = "v1/claimr/token";
635
- const { data } = await this.api.get(`${url}`);
683
+ const data = await this.get(`${url}`);
636
684
  this.claimrToken = data.data.token;
637
685
  }
638
686
  return this.claimrToken;
639
687
  };
640
688
  this.getClaimrData = async ()=>{
641
- const { data } = await this.api.get("/v1/beamable/inventory/skulls");
689
+ const data = await this.get("/v1/beamable/inventory/skulls");
642
690
  return data;
643
691
  };
692
+ this.randomTokenString = ()=>crypto.randomUUID().replace(/-/g, "");
644
693
  // Use the cookie stored in the browser to get the user and save user model in state and local storage
645
694
  // This assumes that the user is logged to backend in and has a cookie jwt
646
- this.getLoggedInUser = ()=>this.api.get("/v1/auth/me");
647
- this.api = axios.create({
648
- baseURL: `${endpoint}`,
649
- withCredentials: true
695
+ this.getLoggedInUser = ()=>this.get("/v1/auth/me");
696
+ this._axios = axios.create({
697
+ baseURL: `${endpoint}`
650
698
  });
651
699
  // Response interceptor for API calls
652
- this.api.interceptors.response.use((response)=>response, (error)=>this.onError(error));
700
+ this._axios.interceptors.response.use((response)=>response, (error)=>this.onError(error));
653
701
  }
654
702
  }
655
703
 
@@ -663,102 +711,67 @@ const getMagic = (magicKey)=>new Magic(magicKey, {
663
711
  new OAuthExtension()
664
712
  ]
665
713
  });
666
- function emailOTPWithMagic(magicKey, email) {
667
- const magic = getMagic(magicKey);
714
+ function emailOTPWithMagic(magicKey, email, magic) {
715
+ magic = magic || getMagic(magicKey);
668
716
  return magic.auth.loginWithEmailOTP({
669
717
  email
670
718
  });
671
719
  }
672
- function telegramWithMagic(magicKey) {
673
- const magic = getMagic(magicKey);
720
+ function telegramWithMagic(magicKey, magic) {
721
+ magic = magic || getMagic(magicKey);
674
722
  return magic.oauth2.loginWithPopup({
675
723
  provider: "telegram"
676
724
  });
677
725
  }
678
- async function tauntMagicTelegramLogin(tauntServiceEndpoint, magicKey, tauntApi) {
679
- const taunt = tauntApi || new TauntApi(tauntServiceEndpoint);
680
- try {
681
- let result = await telegramWithMagic(magicKey);
682
- const errResult = result;
683
- if (errResult.error) {
684
- throw new Error(`No ID token returned ${errResult.error}`);
685
- }
686
- result = result;
687
- console.log("Magic telegram login", {
688
- result
689
- });
690
- return taunt.loginWithMagicDid(result.magic.idToken);
691
- } catch (err) {
692
- console.error("Magic login error:", err);
693
- throw err;
694
- }
726
+ function tauntMagicTelegramLogin(tauntServiceEndpoint, magicKey, tauntApi, extNonce) {
727
+ return withLoginTry(tauntServiceEndpoint, tauntApi, magicKey, undefined, extNonce, (magic)=>telegramWithMagic(magicKey, magic));
695
728
  }
696
- async function tauntMagicEmailOTPLogin(tauntServiceEndpoint, magicKey, email, tauntApi) {
697
- const taunt = tauntApi || new TauntApi(tauntServiceEndpoint);
729
+ function tauntMagicEmailOTPLogin(tauntServiceEndpoint, magicKey, email, tauntApi, extNonce) {
730
+ return withLoginTry(tauntServiceEndpoint, tauntApi, magicKey, undefined, extNonce, (magic)=>emailOTPWithMagic(magicKey, email, magic));
731
+ }
732
+ async function withLoginTry(endpoint, tauntApi, magicKey, magic, extNonce, fn) {
733
+ tauntApi = tauntApi || new TauntApi(endpoint);
734
+ magic = magic || getMagic(magicKey);
698
735
  try {
699
- const did = await emailOTPWithMagic(magicKey, email);
700
- if (!did) throw new Error("No DID returned");
701
- console.log("Magic email OTP login", {
702
- did
703
- });
704
- return taunt.loginWithMagicDid(did);
736
+ if (!await magic.user.isLoggedIn()) {
737
+ await fn(magic, tauntApi);
738
+ }
739
+ // check if user is logged in
740
+ const isLoggedIn = await magic.user.isLoggedIn();
741
+ if (!isLoggedIn) {
742
+ throw new Error("User is not logged in");
743
+ }
744
+ return tauntApi.withProvider({
745
+ getAddress: ()=>magic.rpcProvider.send("eth_accounts", []).then((accounts)=>accounts[0]),
746
+ personalSign: (message, address)=>magic.rpcProvider.send("personal_sign", [
747
+ message,
748
+ address
749
+ ]).then((sig)=>sig)
750
+ }, extNonce);
705
751
  } catch (err) {
706
752
  console.error("Magic login error:", err);
707
753
  throw err;
708
754
  }
709
755
  }
710
- async function tauntMagicDidLogin(tauntServiceEndpoint, did, tauntApi) {
711
- const taunt = tauntApi || new TauntApi(tauntServiceEndpoint);
712
- return taunt.loginWithMagicDid(did);
713
- }
714
756
 
715
- async function tauntSignWithMetamask(tauntServiceEndpoint, provider, tauntApi) {
757
+ async function tauntMetamaskLogin(tauntServiceEndpoint, provider, tauntApi, extNonce) {
716
758
  provider = provider || window.ethereum;
717
- if (!provider) throw new Error("MetaMask provider not found");
718
- const accounts = await provider.request({
719
- method: "eth_requestAccounts"
720
- });
721
- if (!accounts.length) throw new Error("No accounts returned");
722
- console.log("MetaMask", {
723
- accounts
724
- });
725
- const walletAddress = accounts[0];
726
- const cryptoValuesArray = new Uint32Array(3);
727
- const clientNonce = crypto.getRandomValues(cryptoValuesArray).toString();
728
- const taunt = tauntApi || new TauntApi(tauntServiceEndpoint);
729
- const serverNonce = await taunt.nonceLogin(walletAddress, clientNonce);
730
- const payload = JSON.stringify({
731
- clientNonce,
732
- serverNonce
733
- });
734
- const message = `Sign this message with your wallet to connect to Taunt Battleworld ::: ${payload}`;
735
- let signature;
736
- try {
737
- signature = await provider.request({
738
- method: "personal_sign",
739
- params: [
740
- message,
741
- walletAddress
742
- ]
743
- });
744
- } catch (err) {
745
- throw new Error("User denied message signature");
759
+ if (!provider) {
760
+ throw new Error("MetaMask provider not found");
746
761
  }
747
- if (!signature) throw new Error("No signature returned");
748
- return {
749
- walletAddress,
750
- message,
751
- signature
752
- };
753
- }
754
- async function tauntMetamaskLogin(tauntServiceEndpoint, providerParam, tauntApi) {
755
762
  const taunt = tauntApi || new TauntApi(tauntServiceEndpoint);
756
- const { walletAddress, message, signature } = await tauntSignWithMetamask(tauntServiceEndpoint, providerParam, tauntApi);
757
- return taunt.loginWithWeb3WalletSignature({
758
- walletAddress,
759
- message,
760
- signature
761
- });
763
+ return taunt.withProvider({
764
+ getAddress: ()=>provider.request({
765
+ method: "eth_requestAccounts"
766
+ }).then((accounts)=>accounts?.[0]),
767
+ personalSign: (message, address)=>provider.request({
768
+ method: "personal_sign",
769
+ params: [
770
+ message,
771
+ address
772
+ ]
773
+ })
774
+ }, extNonce);
762
775
  }
763
776
 
764
- export { BadGatewayError, BadRequestError, BandwidthLimitExceededError, ConflictError, ErrorFromResponse, ErrorResponse, ExpectationFailedError, FailedDependencyError, ForbiddenError, GatewayTimeoutError, GoneError, HTTPVersionNotSupportedError, ImATeapotError, InsufficientStorageError, InternalServerError, LengthRequiredError, LockedError, LoopDetectedError, MethodNotAllowedError, NetworkAuthenticationRequiredError, NotAcceptableError, NotExtendedError, NotFoundError, NotImplementedError, PaymentRequiredError, PreconditionFailedError, PreconditionRequiredError, ProxyAuthenticationRequiredError, RequestEntityTooLargeError, RequestHeaderFieldsTooLargeError, RequestTimeoutError, RequestUriTooLongError, RequestedRangeNotSatisfiableError, ServiceUnavailableError, TauntApi, TooManyRequestsError, UnauthorizedError, UnknownError, UnprocessableEntityError, UnsupportedMediaTypeError, UpgradeRequiredError, VariantAlsoNegotiatesError, emailOTPWithMagic, tauntMagicDidLogin, tauntMagicEmailOTPLogin, tauntMagicTelegramLogin, tauntMetamaskLogin, tauntSignWithMetamask, telegramWithMagic };
777
+ export { BadGatewayError, BadRequestError, BandwidthLimitExceededError, ConflictError, ErrorFromResponse, ErrorResponse, ExpectationFailedError, FailedDependencyError, ForbiddenError, GatewayTimeoutError, GoneError, HTTPVersionNotSupportedError, ImATeapotError, InsufficientStorageError, InternalServerError, LengthRequiredError, LockedError, LoopDetectedError, MethodNotAllowedError, NetworkAuthenticationRequiredError, NotAcceptableError, NotExtendedError, NotFoundError, NotImplementedError, PaymentRequiredError, PreconditionFailedError, PreconditionRequiredError, ProxyAuthenticationRequiredError, RequestEntityTooLargeError, RequestHeaderFieldsTooLargeError, RequestTimeoutError, RequestUriTooLongError, RequestedRangeNotSatisfiableError, ServiceUnavailableError, TauntApi, TooManyRequestsError, UnauthorizedError, UnknownError, UnprocessableEntityError, UnsupportedMediaTypeError, UpgradeRequiredError, VariantAlsoNegotiatesError, emailOTPWithMagic, tauntMagicEmailOTPLogin, tauntMagicTelegramLogin, tauntMetamaskLogin, telegramWithMagic };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redzone/taunt-logins",
3
- "version": "0.0.8",
3
+ "version": "0.0.10",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "files": [