Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/services/crypto-box/executor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {
AsymmetricEncryptParams,
SignParams,
} from './types'
import { CryptoBoxErrorCodes } from './types'

// 导入加密工具
import {
Expand Down Expand Up @@ -141,7 +142,10 @@ class CryptoExecutor {
if (err instanceof Error && err.message.includes('Address mismatch')) {
throw err
}
throw new Error(`Failed to get keypair for wallet ${walletId}: invalid patternKey or wallet not found`)
throw Object.assign(
new Error('Crypto authorization is invalid. Please re-authorize.'),
{ code: CryptoBoxErrorCodes.INVALID_SESSION_SECRET }
)
}
}

Expand Down
25 changes: 3 additions & 22 deletions src/stackflow/activities/sheets/CryptoAuthorizeJob.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import { useFlow } from '../../stackflow';
import { ActivityParamsProvider, useActivityParams } from '../../hooks';
import { MiniappSheetHeader } from '@/components/ecosystem';
import { PatternLock, patternToString } from '@/components/security/pattern-lock';
import { walletStorageService } from '@/services/wallet-storage';
import {
type CryptoAction,
type TokenDuration,
Expand All @@ -24,6 +23,7 @@ import {
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { walletStore } from '@/stores';
import { superjson } from '@biochain/chain-effect';
import { verifyCryptoAuthorizePattern } from './crypto-authorize-pattern';

type CryptoAuthorizeJobParams = {
/** 请求的操作权限 (superjson 字符串) */
Expand Down Expand Up @@ -66,27 +66,8 @@ function CryptoAuthorizeJobContent() {

try {
const patternKey = patternToString(nodes);

// 验证手势密码是否正确
const wallets = await walletStorageService.getAllWallets();
if (wallets.length === 0) {
setError(true);
setPattern([]);
setIsVerifying(false);
return;
}

let isValid = false;
for (const wallet of wallets) {
try {
await walletStorageService.getMnemonic(wallet.id, patternKey);
isValid = true;
break;
} catch {
// 继续尝试下一个钱包
}
}

// 验证手势密码必须匹配当前目标钱包,避免“任意钱包可解锁”导致后续执行失败
const isValid = await verifyCryptoAuthorizePattern(walletId, patternKey);
if (isValid && walletId) {
// 发送成功事件(包含 walletId 和 selectedDuration 用于 Token 创建)
const event = new CustomEvent('crypto-authorize-confirm', {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { beforeEach, describe, expect, it, vi } from 'vitest'

const { mockGetMnemonic } = vi.hoisted(() => ({
mockGetMnemonic: vi.fn(),
}))

vi.mock('@/services/wallet-storage', () => ({
walletStorageService: {
getMnemonic: mockGetMnemonic,
},
}))

import { verifyCryptoAuthorizePattern } from '../crypto-authorize-pattern'

describe('verifyCryptoAuthorizePattern', () => {
beforeEach(() => {
vi.clearAllMocks()
})

it('returns false when walletId is missing', async () => {
const result = await verifyCryptoAuthorizePattern(undefined, '0-1-2-5-8')
expect(result).toBe(false)
expect(mockGetMnemonic).not.toHaveBeenCalled()
})

it('validates pattern against target wallet only', async () => {
mockGetMnemonic.mockResolvedValueOnce('mnemonic')

const result = await verifyCryptoAuthorizePattern('wallet-target', '0-1-2-5-8')

expect(result).toBe(true)
expect(mockGetMnemonic).toHaveBeenCalledTimes(1)
expect(mockGetMnemonic).toHaveBeenCalledWith('wallet-target', '0-1-2-5-8')
})

it('returns false when target wallet pattern is invalid', async () => {
mockGetMnemonic.mockRejectedValueOnce(new Error('Failed to decrypt mnemonic'))

const result = await verifyCryptoAuthorizePattern('wallet-target', '0-1-2-5-8')

expect(result).toBe(false)
expect(mockGetMnemonic).toHaveBeenCalledTimes(1)
expect(mockGetMnemonic).toHaveBeenCalledWith('wallet-target', '0-1-2-5-8')
})
})
11 changes: 11 additions & 0 deletions src/stackflow/activities/sheets/crypto-authorize-pattern.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { walletStorageService } from '@/services/wallet-storage'

export async function verifyCryptoAuthorizePattern(walletId: string | undefined, patternKey: string): Promise<boolean> {
if (!walletId) return false
try {
await walletStorageService.getMnemonic(walletId, patternKey)
return true
} catch {
return false
}
}