mirror of
https://github.com/block-core/angor-hub-old.git
synced 2026-01-31 07:34:21 +01:00
Add nostr-login
This commit is contained in:
5204
package-lock.json
generated
5204
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,8 @@
|
||||
"@angular/pwa": "^18.2.8",
|
||||
"@angular/router": "18.2.8",
|
||||
"@angular/service-worker": "^18.2.8",
|
||||
"@blockcore/nostr-login": "^1.0.6",
|
||||
"@blockcore/nostr-login": "^1.0.7",
|
||||
"@blockcore/nostr-login-components": "^1.0.7",
|
||||
"@ctrl/ngx-emoji-mart": "^9.2.0",
|
||||
"@gandlaf21/bolt11-decode": "^3.1.1",
|
||||
"@getalby/lightning-tools": "^5.0.3",
|
||||
@@ -50,7 +51,7 @@
|
||||
"blurhash": "^2.0.5",
|
||||
"buffer": "^6.0.3",
|
||||
"cropperjs": "^1.6.2",
|
||||
"crypto-browserify": "^3.12.0",
|
||||
"crypto-browserify": "^3.3.0",
|
||||
"crypto-js": "4.2.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"dompurify": "^3.1.7",
|
||||
@@ -58,7 +59,7 @@
|
||||
"install": "^0.13.0",
|
||||
"jsdom": "^25.0.1",
|
||||
"light-bolt11-decoder": "^3.2.0",
|
||||
"lnd-grpc": "^0.5.4",
|
||||
"lnd-grpc": "^0.4.6",
|
||||
"localforage": "^1.10.0",
|
||||
"lodash-es": "4.17.21",
|
||||
"luxon": "3.5.0",
|
||||
@@ -81,7 +82,7 @@
|
||||
"zone.js": "0.15.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-devkit/build-angular": "18.2.8",
|
||||
"@angular-devkit/build-angular": "^18.2.9",
|
||||
"@angular/cli": "18.2.8",
|
||||
"@angular/compiler-cli": "18.2.8",
|
||||
"@tailwindcss/typography": "0.5.15",
|
||||
|
||||
@@ -11,277 +11,317 @@
|
||||
>
|
||||
Login
|
||||
</div>
|
||||
<div class="mt-0.5 flex items-baseline font-medium">
|
||||
<div>Don't have an account?</div>
|
||||
<a
|
||||
class="ml-1 text-primary-500 hover:underline"
|
||||
[routerLink]="['/register']"
|
||||
>Register</a
|
||||
<div *ngIf="!useNostrLogin">
|
||||
<div class="mt-0.5 flex items-baseline font-medium">
|
||||
<div>Don't have an account?</div>
|
||||
<a
|
||||
class="ml-1 text-primary-500 hover:underline"
|
||||
[routerLink]="['/register']"
|
||||
>Register</a
|
||||
>
|
||||
</div>
|
||||
|
||||
<angor-alert
|
||||
*ngIf="showSecAlert"
|
||||
class="mt-8"
|
||||
[appearance]="'outline'"
|
||||
[showIcon]="false"
|
||||
[type]="secAlert.type"
|
||||
[@shake]="secAlert.type === 'error'"
|
||||
>
|
||||
</div>
|
||||
{{ secAlert.message }}
|
||||
</angor-alert>
|
||||
|
||||
<angor-alert
|
||||
*ngIf="showSecAlert"
|
||||
class="mt-8"
|
||||
[appearance]="'outline'"
|
||||
[showIcon]="false"
|
||||
[type]="secAlert.type"
|
||||
[@shake]="secAlert.type === 'error'"
|
||||
>
|
||||
{{ secAlert.message }}
|
||||
</angor-alert>
|
||||
<div>
|
||||
<!-- Separator -->
|
||||
<div class="mt-8 flex items-center">
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
<div class="text-secondary mx-2">
|
||||
Login with extension
|
||||
</div>
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
</div>
|
||||
|
||||
<!-- extension login buttons -->
|
||||
<div class="mt-8 flex items-center space-x-4">
|
||||
<button
|
||||
class="flex-auto space-x-2"
|
||||
type="button"
|
||||
mat-stroked-button
|
||||
(click)="loginWithNostrExtension()"
|
||||
>
|
||||
<mat-icon
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'feather:zap'"
|
||||
></mat-icon>
|
||||
<span>Login with Nostr Extension</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 flex items-center">
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
<div class="text-secondary mx-2">Or</div>
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Login form with Secret Key -->
|
||||
<form
|
||||
class="mt-8"
|
||||
[formGroup]="SecretKeyLoginForm"
|
||||
(ngSubmit)="loginWithSecretKey()"
|
||||
>
|
||||
<!-- secret key field -->
|
||||
<div class="mt-8 flex items-center">
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
<div class="text-secondary mx-2">Enter secret key</div>
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
</div>
|
||||
<mat-form-field class="w-full">
|
||||
<mat-label>Secret Key</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="secretKey"
|
||||
autocomplete="secretKey"
|
||||
/>
|
||||
@if (
|
||||
SecretKeyLoginForm.get('secretKey').hasError(
|
||||
'required'
|
||||
)
|
||||
) {
|
||||
<mat-error> Secret key is required </mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Password field -->
|
||||
<mat-form-field class="w-full">
|
||||
<mat-label>Password</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="password"
|
||||
[formControlName]="'password'"
|
||||
autocomplete="current-password-seckey"
|
||||
#secretPasswordField
|
||||
/>
|
||||
<button
|
||||
mat-icon-button
|
||||
type="button"
|
||||
(click)="
|
||||
secretPasswordField.type === 'password'
|
||||
? (secretPasswordField.type = 'text')
|
||||
: (secretPasswordField.type = 'password')
|
||||
"
|
||||
matSuffix
|
||||
>
|
||||
<mat-icon
|
||||
*ngIf="secretPasswordField.type === 'password'"
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'heroicons_solid:eye'"
|
||||
></mat-icon>
|
||||
<mat-icon
|
||||
*ngIf="secretPasswordField.type === 'text'"
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'heroicons_solid:eye-slash'"
|
||||
></mat-icon>
|
||||
</button>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
SecretKeyLoginForm.get('password').hasError(
|
||||
'required'
|
||||
)
|
||||
"
|
||||
>
|
||||
Password is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Submit button -->
|
||||
<button
|
||||
class="angor-mat-button-large mt-6 w-full"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
[disabled]="SecretKeyLoginForm.invalid"
|
||||
>
|
||||
<span *ngIf="!loading">Login</span>
|
||||
<mat-progress-spinner
|
||||
*ngIf="loading"
|
||||
diameter="24"
|
||||
mode="indeterminate"
|
||||
></mat-progress-spinner>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div *ngIf="isInstalledExtension">
|
||||
<!-- Separator -->
|
||||
<div class="mt-8 flex items-center">
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
<div class="text-secondary mx-2">Login with extension</div>
|
||||
<div class="text-secondary mx-2">Or enter menemonic</div>
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
</div>
|
||||
|
||||
<!-- extension login buttons -->
|
||||
<angor-alert
|
||||
*ngIf="showMenemonicAlert"
|
||||
class="mt-8"
|
||||
[appearance]="'outline'"
|
||||
[showIcon]="false"
|
||||
[type]="menemonicAlert.type"
|
||||
[@shake]="menemonicAlert.type === 'error'"
|
||||
>
|
||||
{{ menemonicAlert.message }}
|
||||
</angor-alert>
|
||||
<!-- Login form with Menemonic -->
|
||||
<form
|
||||
class="mt-8"
|
||||
[formGroup]="MenemonicLoginForm"
|
||||
(ngSubmit)="loginWithMenemonic()"
|
||||
>
|
||||
<!-- Menemonic field -->
|
||||
<mat-form-field class="w-full">
|
||||
<mat-label>Menemonic</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="menemonic"
|
||||
autocomplete="menemonic"
|
||||
/>
|
||||
@if (
|
||||
MenemonicLoginForm.get('menemonic').hasError(
|
||||
'required'
|
||||
)
|
||||
) {
|
||||
<mat-error> Menemonic is required </mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Passphrase field -->
|
||||
<mat-form-field class="w-full">
|
||||
<mat-label>Passphrase (Optional)</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="password"
|
||||
[formControlName]="'passphrase'"
|
||||
autocomplete="current-passphrase-menemonic"
|
||||
#passphraseField
|
||||
/>
|
||||
<button
|
||||
mat-icon-button
|
||||
type="button"
|
||||
(click)="
|
||||
passphraseField.type === 'password'
|
||||
? (passphraseField.type = 'text')
|
||||
: (passphraseField.type = 'password')
|
||||
"
|
||||
matSuffix
|
||||
>
|
||||
<mat-icon
|
||||
*ngIf="passphraseField.type === 'password'"
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'heroicons_solid:eye'"
|
||||
></mat-icon>
|
||||
<mat-icon
|
||||
*ngIf="passphraseField.type === 'text'"
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'heroicons_solid:eye-slash'"
|
||||
></mat-icon>
|
||||
</button>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
MenemonicLoginForm.get('passphrase').hasError(
|
||||
'required'
|
||||
)
|
||||
"
|
||||
>
|
||||
Passphrase is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Password field -->
|
||||
<mat-form-field class="w-full">
|
||||
<mat-label>Password</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="password"
|
||||
[formControlName]="'password'"
|
||||
autocomplete="current-password-menemonic"
|
||||
#menemonicPasswordField
|
||||
/>
|
||||
<button
|
||||
mat-icon-button
|
||||
type="button"
|
||||
(click)="
|
||||
menemonicPasswordField.type === 'password'
|
||||
? (menemonicPasswordField.type = 'text')
|
||||
: (menemonicPasswordField.type = 'password')
|
||||
"
|
||||
matSuffix
|
||||
>
|
||||
<mat-icon
|
||||
*ngIf="
|
||||
menemonicPasswordField.type === 'password'
|
||||
"
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'heroicons_solid:eye'"
|
||||
></mat-icon>
|
||||
<mat-icon
|
||||
*ngIf="menemonicPasswordField.type === 'text'"
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'heroicons_solid:eye-slash'"
|
||||
></mat-icon>
|
||||
</button>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
MenemonicLoginForm.get('password').hasError(
|
||||
'required'
|
||||
)
|
||||
"
|
||||
>
|
||||
Password is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Submit button -->
|
||||
<button
|
||||
class="angor-mat-button-large mt-6 w-full"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
[disabled]="MenemonicLoginForm.invalid"
|
||||
>
|
||||
<span *ngIf="!loading">Login</span>
|
||||
<mat-progress-spinner
|
||||
*ngIf="loading"
|
||||
diameter="24"
|
||||
mode="indeterminate"
|
||||
></mat-progress-spinner>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
<div *ngIf="useNostrLogin">
|
||||
<div class="mt-8 flex items-center space-x-4">
|
||||
<button
|
||||
class="flex-auto space-x-2"
|
||||
type="button"
|
||||
mat-stroked-button
|
||||
(click)="loginWithNostrExtension()"
|
||||
(click)="loginWithNostrAccount()"
|
||||
>
|
||||
<mat-icon
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'feather:zap'"
|
||||
></mat-icon>
|
||||
<span>Login with Nostr Extension</span>
|
||||
<span>Login with Nostr Account</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="mt-8 flex items-center">
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
<div class="text-secondary mx-2">Or</div>
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
<div class="mt-8 flex items-center space-x-4">
|
||||
<button
|
||||
class="flex-auto space-x-2"
|
||||
type="button"
|
||||
mat-stroked-button
|
||||
(click)="signUpWithNostrAccount()"
|
||||
>
|
||||
<mat-icon
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'feather:zap'"
|
||||
></mat-icon>
|
||||
<span>Sign up with Nostr Account</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Login form with Secret Key -->
|
||||
<form
|
||||
class="mt-8"
|
||||
[formGroup]="SecretKeyLoginForm"
|
||||
(ngSubmit)="loginWithSecretKey()"
|
||||
>
|
||||
<!-- secret key field -->
|
||||
<div class="mt-8 flex items-center">
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
<div class="text-secondary mx-2">Enter secret key</div>
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
</div>
|
||||
<mat-form-field class="w-full">
|
||||
<mat-label>Secret Key</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="secretKey"
|
||||
autocomplete="secretKey"
|
||||
/>
|
||||
@if (
|
||||
SecretKeyLoginForm.get('secretKey').hasError('required')
|
||||
) {
|
||||
<mat-error> Secret key is required </mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Password field -->
|
||||
<mat-form-field class="w-full">
|
||||
<mat-label>Password</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="password"
|
||||
[formControlName]="'password'"
|
||||
autocomplete="current-password-seckey"
|
||||
#secretPasswordField
|
||||
/>
|
||||
<button
|
||||
mat-icon-button
|
||||
type="button"
|
||||
(click)="
|
||||
secretPasswordField.type === 'password'
|
||||
? (secretPasswordField.type = 'text')
|
||||
: (secretPasswordField.type = 'password')
|
||||
"
|
||||
matSuffix
|
||||
>
|
||||
<mat-icon
|
||||
*ngIf="secretPasswordField.type === 'password'"
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'heroicons_solid:eye'"
|
||||
></mat-icon>
|
||||
<mat-icon
|
||||
*ngIf="secretPasswordField.type === 'text'"
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'heroicons_solid:eye-slash'"
|
||||
></mat-icon>
|
||||
</button>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
SecretKeyLoginForm.get('password').hasError(
|
||||
'required'
|
||||
)
|
||||
"
|
||||
>
|
||||
Password is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Submit button -->
|
||||
<button
|
||||
class="angor-mat-button-large mt-6 w-full"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
[disabled]="SecretKeyLoginForm.invalid"
|
||||
>
|
||||
<span *ngIf="!loading">Login</span>
|
||||
<mat-progress-spinner
|
||||
*ngIf="loading"
|
||||
diameter="24"
|
||||
mode="indeterminate"
|
||||
></mat-progress-spinner>
|
||||
</button>
|
||||
</form>
|
||||
|
||||
<div class="mt-8 flex items-center">
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
<div class="text-secondary mx-2">Or enter menemonic</div>
|
||||
<div class="mt-px flex-auto border-t"></div>
|
||||
</div>
|
||||
|
||||
<angor-alert
|
||||
*ngIf="showMenemonicAlert"
|
||||
class="mt-8"
|
||||
[appearance]="'outline'"
|
||||
[showIcon]="false"
|
||||
[type]="menemonicAlert.type"
|
||||
[@shake]="menemonicAlert.type === 'error'"
|
||||
>
|
||||
{{ menemonicAlert.message }}
|
||||
</angor-alert>
|
||||
<!-- Login form with Menemonic -->
|
||||
<form
|
||||
class="mt-8"
|
||||
[formGroup]="MenemonicLoginForm"
|
||||
(ngSubmit)="loginWithMenemonic()"
|
||||
>
|
||||
<!-- Menemonic field -->
|
||||
<mat-form-field class="w-full">
|
||||
<mat-label>Menemonic</mat-label>
|
||||
<input
|
||||
matInput
|
||||
formControlName="menemonic"
|
||||
autocomplete="menemonic"
|
||||
/>
|
||||
@if (
|
||||
MenemonicLoginForm.get('menemonic').hasError('required')
|
||||
) {
|
||||
<mat-error> Menemonic is required </mat-error>
|
||||
}
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Passphrase field -->
|
||||
<mat-form-field class="w-full">
|
||||
<mat-label>Passphrase (Optional)</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="password"
|
||||
[formControlName]="'passphrase'"
|
||||
autocomplete="current-passphrase-menemonic"
|
||||
#passphraseField
|
||||
/>
|
||||
<button
|
||||
mat-icon-button
|
||||
type="button"
|
||||
(click)="
|
||||
passphraseField.type === 'password'
|
||||
? (passphraseField.type = 'text')
|
||||
: (passphraseField.type = 'password')
|
||||
"
|
||||
matSuffix
|
||||
>
|
||||
<mat-icon
|
||||
*ngIf="passphraseField.type === 'password'"
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'heroicons_solid:eye'"
|
||||
></mat-icon>
|
||||
<mat-icon
|
||||
*ngIf="passphraseField.type === 'text'"
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'heroicons_solid:eye-slash'"
|
||||
></mat-icon>
|
||||
</button>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
MenemonicLoginForm.get('passphrase').hasError(
|
||||
'required'
|
||||
)
|
||||
"
|
||||
>
|
||||
Passphrase is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Password field -->
|
||||
<mat-form-field class="w-full">
|
||||
<mat-label>Password</mat-label>
|
||||
<input
|
||||
matInput
|
||||
type="password"
|
||||
[formControlName]="'password'"
|
||||
autocomplete="current-password-menemonic"
|
||||
#menemonicPasswordField
|
||||
/>
|
||||
<button
|
||||
mat-icon-button
|
||||
type="button"
|
||||
(click)="
|
||||
menemonicPasswordField.type === 'password'
|
||||
? (menemonicPasswordField.type = 'text')
|
||||
: (menemonicPasswordField.type = 'password')
|
||||
"
|
||||
matSuffix
|
||||
>
|
||||
<mat-icon
|
||||
*ngIf="menemonicPasswordField.type === 'password'"
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'heroicons_solid:eye'"
|
||||
></mat-icon>
|
||||
<mat-icon
|
||||
*ngIf="menemonicPasswordField.type === 'text'"
|
||||
class="icon-size-5"
|
||||
[svgIcon]="'heroicons_solid:eye-slash'"
|
||||
></mat-icon>
|
||||
</button>
|
||||
<mat-error
|
||||
*ngIf="
|
||||
MenemonicLoginForm.get('password').hasError(
|
||||
'required'
|
||||
)
|
||||
"
|
||||
>
|
||||
Password is required
|
||||
</mat-error>
|
||||
</mat-form-field>
|
||||
|
||||
<!-- Submit button -->
|
||||
<button
|
||||
class="angor-mat-button-large mt-6 w-full"
|
||||
mat-flat-button
|
||||
color="primary"
|
||||
[disabled]="MenemonicLoginForm.invalid"
|
||||
>
|
||||
<span *ngIf="!loading">Login</span>
|
||||
<mat-progress-spinner
|
||||
*ngIf="loading"
|
||||
diameter="24"
|
||||
mode="indeterminate"
|
||||
></mat-progress-spinner>
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
|
||||
@@ -17,7 +17,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
||||
import { Router, RouterLink } from '@angular/router';
|
||||
import { SignerService } from 'app/services/signer.service';
|
||||
import { StateService } from 'app/services/state.service';
|
||||
|
||||
import { init as initNostrLogin, launch as launchNostrLoginDialog } from '@blockcore/nostr-login';
|
||||
@Component({
|
||||
selector: 'auth-sign-in',
|
||||
templateUrl: './login.component.html',
|
||||
@@ -34,7 +34,7 @@ import { StateService } from 'app/services/state.service';
|
||||
MatCheckboxModule,
|
||||
MatProgressSpinnerModule,
|
||||
CommonModule,
|
||||
],
|
||||
],
|
||||
})
|
||||
export class LoginComponent implements OnInit {
|
||||
SecretKeyLoginForm: FormGroup;
|
||||
@@ -52,6 +52,8 @@ export class LoginComponent implements OnInit {
|
||||
npub: string = '';
|
||||
nsec: string = '';
|
||||
|
||||
useNostrLogin = false;
|
||||
|
||||
constructor(
|
||||
private _formBuilder: FormBuilder,
|
||||
private _router: Router,
|
||||
@@ -60,8 +62,32 @@ export class LoginComponent implements OnInit {
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
|
||||
this.initializeForms();
|
||||
this.checkNostrExtensionAvailability();
|
||||
|
||||
initNostrLogin({
|
||||
theme: 'ocean',
|
||||
noBanner: true,
|
||||
title:'Angor Hub',
|
||||
onAuth: (npub: string, options: any) => {
|
||||
console.log('User authenticated:', npub);
|
||||
alert('User authenticated: ' + npub);
|
||||
},
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private async loginWithNostrAccount(): Promise<void> {
|
||||
launchNostrLoginDialog(
|
||||
'welcome-login',
|
||||
);
|
||||
}
|
||||
|
||||
private async signUpWithNostrAccount(): Promise<void> {
|
||||
launchNostrLoginDialog(
|
||||
'welcome-signup',
|
||||
);
|
||||
}
|
||||
|
||||
private async initializeAppState(): Promise<void> {
|
||||
|
||||
@@ -145,42 +145,48 @@ export class SignerService {
|
||||
}
|
||||
|
||||
//seckey===============
|
||||
async setSecretKey(secretKey: string, password: string) {
|
||||
const encryptedSecretKey = await this.securityService.encryptData(
|
||||
secretKey,
|
||||
password
|
||||
);
|
||||
localStorage.setItem(
|
||||
this.localStorageSecretKeyName,
|
||||
encryptedSecretKey
|
||||
);
|
||||
async setSecretKey(secretKey: string, password: string = "") {
|
||||
if (password === "") {
|
||||
localStorage.setItem(this.localStorageSecretKeyName, secretKey);
|
||||
localStorage.setItem('usePassword', 'false');
|
||||
} else {
|
||||
const encryptedSecretKey = await this.securityService.encryptData(secretKey, password);
|
||||
localStorage.setItem(this.localStorageSecretKeyName, encryptedSecretKey);
|
||||
localStorage.setItem('usePassword', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
async getSecretKey(password: string) {
|
||||
const encryptedSecretKey = localStorage.getItem(
|
||||
this.localStorageSecretKeyName
|
||||
);
|
||||
async getSecretKey(password: string = "") {
|
||||
const encryptedSecretKey = localStorage.getItem(this.localStorageSecretKeyName);
|
||||
const usePassword = localStorage.getItem('usePassword') === 'true';
|
||||
if (!encryptedSecretKey) {
|
||||
return null;
|
||||
}
|
||||
return await this.securityService.decryptData(
|
||||
encryptedSecretKey,
|
||||
password
|
||||
);
|
||||
|
||||
if (!usePassword) {
|
||||
return encryptedSecretKey;
|
||||
}
|
||||
|
||||
return await this.securityService.decryptData(encryptedSecretKey, password);
|
||||
}
|
||||
|
||||
|
||||
async getDecryptedSecretKey(): Promise<string | null> {
|
||||
try {
|
||||
const storedPassword = this.getPassword(); // Ensure this retrieves a valid password
|
||||
if (storedPassword) {
|
||||
return await this.getSecretKey(storedPassword); // Ensure getSecretKey returns a valid private key
|
||||
const usePassword = localStorage.getItem('usePassword') === 'true';
|
||||
|
||||
if (!usePassword) {
|
||||
return this.getSecretKey();
|
||||
}
|
||||
|
||||
const result = await this.requestPassword(); // Prompt user for password if not stored
|
||||
const storedPassword = this.getPassword();
|
||||
if (storedPassword) {
|
||||
return await this.getSecretKey(storedPassword);
|
||||
}
|
||||
|
||||
const result = await this.requestPassword();
|
||||
if (result?.password) {
|
||||
const decryptedPrivateKey = await this.getSecretKey(
|
||||
result.password
|
||||
); // Check that the private key is decrypted properly
|
||||
const decryptedPrivateKey = await this.getSecretKey(result.password);
|
||||
if (result.duration !== 0) {
|
||||
this.savePassword(result.password, result.duration);
|
||||
}
|
||||
@@ -195,28 +201,41 @@ export class SignerService {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//nsec===============
|
||||
async setNsec(nsec: string, password: string) {
|
||||
const encryptedNsec = await this.securityService.encryptData(
|
||||
nsec,
|
||||
password
|
||||
);
|
||||
localStorage.setItem(this.localStorageNsecName, encryptedNsec);
|
||||
|
||||
async setNsec(nsec: string, password: string = "") {
|
||||
if (password === "") {
|
||||
localStorage.setItem(this.localStorageNsecName, nsec);
|
||||
localStorage.setItem('usePassword', 'false');
|
||||
} else {
|
||||
const encryptedNsec = await this.securityService.encryptData(nsec, password);
|
||||
localStorage.setItem(this.localStorageNsecName, encryptedNsec);
|
||||
localStorage.setItem('usePassword', 'true');
|
||||
}
|
||||
}
|
||||
|
||||
async getNsec(password: string) {
|
||||
async getNsec(password: string = "") {
|
||||
const encryptedNsec = localStorage.getItem(this.localStorageNsecName);
|
||||
const usePassword = localStorage.getItem('usePassword') === 'true';
|
||||
|
||||
if (!encryptedNsec) {
|
||||
return null;
|
||||
}
|
||||
return await this.securityService.decryptData(encryptedNsec, password);
|
||||
|
||||
if (!usePassword) {
|
||||
return encryptedNsec;
|
||||
}
|
||||
|
||||
return await this.securityService.decryptData(encryptedNsec, password);
|
||||
}
|
||||
|
||||
|
||||
setPublicKeyFromExtension(publicKey: string) {
|
||||
this.setPublicKey(publicKey);
|
||||
}
|
||||
|
||||
handleLoginWithKey(key: string, password: string): boolean {
|
||||
handleLoginWithKey(key: string, password: string=""): boolean {
|
||||
let secretKey: string;
|
||||
let pubkey: string;
|
||||
let nsec: string;
|
||||
|
||||
@@ -89,14 +89,6 @@ export class Utilities {
|
||||
}
|
||||
}
|
||||
|
||||
ensureHexIdentifier(pubkey: string) {
|
||||
if (pubkey.startsWith('npub')) {
|
||||
pubkey = this.arrayToHex(this.convertFromBech32(pubkey));
|
||||
}
|
||||
|
||||
return pubkey;
|
||||
}
|
||||
|
||||
copy(text: string) {
|
||||
this.copyToClipboard(text);
|
||||
|
||||
@@ -170,25 +162,6 @@ export class Utilities {
|
||||
return bytesToHex(value);
|
||||
}
|
||||
|
||||
convertFromBech32(address: string) {
|
||||
const decoded = bech32.decode(address);
|
||||
const key = bech32.fromWords(decoded.words);
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
convertFromBech32ToHex(address: string) {
|
||||
const decoded = bech32.decode(address);
|
||||
const key = bech32.fromWords(decoded.words);
|
||||
return this.arrayToHex(key);
|
||||
}
|
||||
|
||||
convertBech32ToText(str: string) {
|
||||
const decoded = bech32.decode(str, 1000);
|
||||
const buf = bech32.fromWords(decoded.words);
|
||||
return new TextDecoder().decode(Uint8Array.from(buf));
|
||||
}
|
||||
|
||||
keyToHex(publicKey: Uint8Array) {
|
||||
return bytesToHex(publicKey);
|
||||
}
|
||||
|
||||
@@ -1,21 +1,31 @@
|
||||
/* To learn more about this file see: https://angular.io/config/tsconfig. */
|
||||
{
|
||||
"compileOnSave": false,
|
||||
"compilerOptions": {
|
||||
"baseUrl": "./src",
|
||||
"outDir": "./dist/out-tsc",
|
||||
"paths": {
|
||||
"@blockcore/*": ["node_modules/@blockcore/*"]
|
||||
},
|
||||
"esModuleInterop": true,
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"declaration": true,
|
||||
"experimentalDecorators": true,
|
||||
"moduleResolution": "bundler",
|
||||
"importHelpers": true,
|
||||
"target": "ES2022",
|
||||
"module": "ES2022",
|
||||
"useDefineForClassFields": false,
|
||||
"lib": ["ES2022", "dom"]
|
||||
"lib": ["ES2022", "dom"],
|
||||
"strict": false,
|
||||
"noImplicitOverride": false,
|
||||
"noImplicitReturns": false,
|
||||
"noFallthroughCasesInSwitch": false,
|
||||
"skipLibCheck": true
|
||||
},
|
||||
"angularCompilerOptions": {
|
||||
"enableI18nLegacyMessageIdFormat": false
|
||||
"enableI18nLegacyMessageIdFormat": false,
|
||||
"strictInjectionParameters": false,
|
||||
"strictInputAccessModifiers": false,
|
||||
"strictTemplates": false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user