Skip to content
Open
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
1 change: 1 addition & 0 deletions packages/snap/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Changed

- Show a self-send warning in the send confirmation when the recipient address belongs to the sending account ([#607](https://github.com/MetaMask/snap-bitcoin-wallet/pull/607))
- Show a confirmation dialog before signing a PSBT from KeyringHandler and sending a transfer ([#591](https://github.com/MetaMask/snap-bitcoin-wallet/pull/591))
- Add `resolveAccountAddress` method to KeyringHandler for dApp connectivity ([#590](https://github.com/MetaMask/snap-bitcoin-wallet/pull/590))

Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "Transaktionsanfrage"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Anfrage von"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/el.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "Αίτημα συναλλαγής"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Ζητήθηκε από"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "Transaction request"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Request from"
},
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "Solicitud de transacción"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Solicitud de"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/es_419.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "Solicitud de transacción"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Solicitud de"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "Demande de transaction"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Demande de la part de"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/hi.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "ट्रांसेक्शन रिक्वेस्ट"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "इनसे मिला अनुरोध"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/id.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "Permintaan transaksi"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Permintaan dari"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/ja.json
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "トランザクションリクエスト"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "要求元"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/ko.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "트랜잭션 요청"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "요청자:"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/pt.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "Solicitação de transação"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Solicitação de"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/ru.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "Запрос транзакции"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Запрос от"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/tl.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "Hiling na transaksyon"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Kahilingan mula sa/kay"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/tr.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "İşlem talebi"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Talebi gönderen"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/vi.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "Yêu cầu giao dịch"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Yêu cầu từ"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/locales/zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "交易请求"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "请求来自"
}
Expand Down
6 changes: 6 additions & 0 deletions packages/snap/messages.json
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,12 @@
"confirmation.signAndSendTransaction.title": {
"message": "Transaction request"
},
"confirmation.signAndSendTransaction.selfSend.title": {
"message": "Sending to your own address"
},
"confirmation.signAndSendTransaction.selfSend.description": {
"message": "The recipient address belongs to this wallet. The amount will stay in your account, but network fees still apply."
},
"confirmation.requestOrigin": {
"message": "Request from"
},
Expand Down
2 changes: 1 addition & 1 deletion packages/snap/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/MetaMask/snap-bitcoin-wallet.git"
},
"source": {
"shasum": "1jbPT93y4v8JjV5Sj8zdfhhk9Eq1GJrTjSjciRYsl4c=",
"shasum": "ULNv7Bt/BuxJkLiIo7x79kO0vVLtnZj8CxGoa2bEQ+M=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
1 change: 1 addition & 0 deletions packages/snap/src/entities/send-flow.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export type ConfirmSendFormContext = {
locale: string;
psbt: string;
origin?: string;
isMine: boolean;
};

export type SendFormContext = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Psbt } from '@metamask/bitcoindevkit';
import type { SnapComponent } from '@metamask/snaps-sdk/jsx';
import {
Address,
Banner,
Heading,
Link,
Section,
Expand Down Expand Up @@ -43,6 +44,7 @@ export const UnifiedSendFormView: SnapComponent<UnifiedSendFormViewProps> = ({
recipient,
explorerUrl,
origin,
isMine,
} = context;

const psbt = Psbt.from_string(context.psbt);
Expand All @@ -60,6 +62,17 @@ export const UnifiedSendFormView: SnapComponent<UnifiedSendFormViewProps> = ({
<Box>{null}</Box>
</Box>

{isMine ? (
<Banner
title={t('confirmation.signAndSendTransaction.selfSend.title')}
severity="warning"
>
<SnapText>
{t('confirmation.signAndSendTransaction.selfSend.description')}
</SnapText>
</Banner>
) : null}

<Section>
<Box>
<SnapText fontWeight="medium" color="alternative">
Expand Down
46 changes: 46 additions & 0 deletions packages/snap/src/store/JSXConfirmationRepository.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { UnifiedSendFormView } from '../infra/jsx/unified-send-flow';
jest.mock('@metamask/bitcoindevkit', () => ({
Address: {
from_script: jest.fn(),
from_string: jest.fn(),
},
}));

Expand Down Expand Up @@ -110,10 +111,12 @@ describe('JSXConfirmationRepository', () => {
});

describe('insertSendTransfer', () => {
const mockRecipientScript = mock<ScriptBuf>();
const mockAccount = mock<BitcoinAccount>({
id: 'account-id',
network: 'bitcoin',
publicAddress: mock<Address>({ toString: () => 'fromAddress' }),
isMine: () => false,
});
const mockPsbt = mock<Psbt>({
toString: () => 'serialized-psbt',
Expand All @@ -132,6 +135,9 @@ describe('JSXConfirmationRepository', () => {
mockRatesClient.spotPrices.mockResolvedValue(
mock<SpotPrice>({ price: 50000 }),
);
MockedBdkAddress.from_string.mockReturnValue(
mock<Address>({ script_pubkey: mockRecipientScript }),
);
});

it('creates and displays a send transfer interface', async () => {
Expand All @@ -151,6 +157,7 @@ describe('JSXConfirmationRepository', () => {
locale: 'en',
psbt: 'serialized-psbt',
origin,
isMine: false,
};

expect(mockSnapClient.getPreferences).toHaveBeenCalled();
Expand All @@ -170,6 +177,44 @@ describe('JSXConfirmationRepository', () => {
);
});

it('marks the recipient as isMine when it belongs to the account', async () => {
const selfSendAccount = mock<BitcoinAccount>({
id: 'account-id',
network: 'bitcoin',
publicAddress: mock<Address>({ toString: () => 'fromAddress' }),
isMine: () => true,
});

await repo.insertSendTransfer(
selfSendAccount,
mockPsbt,
recipient,
origin,
);

expect(MockedBdkAddress.from_string).toHaveBeenCalledWith(
recipient.address,
selfSendAccount.network,
);
expect(mockSnapClient.createInterface).toHaveBeenCalledWith(
undefined,
expect.objectContaining({ isMine: true }),
);
});

it('defaults isMine to false when the recipient address fails to parse', async () => {
MockedBdkAddress.from_string.mockImplementation(() => {
throw new Error('Invalid address');
});

await repo.insertSendTransfer(mockAccount, mockPsbt, recipient, origin);

expect(mockSnapClient.createInterface).toHaveBeenCalledWith(
undefined,
expect.objectContaining({ isMine: false }),
);
});

it('throws UserActionError if the user cancels', async () => {
mockSnapClient.displayConfirmation.mockResolvedValue(false);
await expect(
Expand All @@ -182,6 +227,7 @@ describe('JSXConfirmationRepository', () => {
id: 'account-id',
network: 'testnet',
publicAddress: mock<Address>({ toString: () => 'fromAddress' }),
isMine: () => false,
});

await repo.insertSendTransfer(
Expand Down
12 changes: 12 additions & 0 deletions packages/snap/src/store/JSXConfirmationRepository.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ export class JSXConfirmationRepository implements ConfirmationRepository {
const { locale, currency: fiatCurrency } =
await this.#snapClient.getPreferences();

let isMine = false;
try {
const recipientScript = BdkAddress.from_string(
recipient.address,
account.network,
).script_pubkey;
isMine = account.isMine(recipientScript);
} catch {
isMine = false;
}

const context: ConfirmSendFormContext = {
from: account.publicAddress.toString(),
explorerUrl: this.#chainClient.getExplorerUrl(account.network),
Expand All @@ -99,6 +110,7 @@ export class JSXConfirmationRepository implements ConfirmationRepository {
locale,
psbt: psbt.toString(),
origin,
isMine,
};

const messages = await this.#translator.load(locale);
Expand Down
Loading
Loading