Skip to content

Commit

Permalink
Merge pull request #256 from yours-org/spv-wallet-browser-merge
Browse files Browse the repository at this point in the history
Spv wallet browser merge
  • Loading branch information
danwag06 authored Nov 6, 2024
2 parents 6f7223c + 2d914e3 commit 006af47
Show file tree
Hide file tree
Showing 23 changed files with 2,559 additions and 3,491 deletions.
33 changes: 33 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Run Tests

on:
push:
branches:
- main
pull_request:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v3

- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '20'

- name: Install dependencies
run: yarn install

- name: Run tests if available
run: |
if [ -n "$(find . -name '*.test.js' -o -name '*.test.ts' -o -name '*.spec.js' -o -name '*.spec.ts')" ]; then
yarn test --passWithNoTests
else
echo "No test files found. Skipping tests."
fi
4,396 changes: 1,117 additions & 3,279 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
"dependencies": {
"@bsv/paymail": "^2.0.2",
"@bsv/sdk": "^1.1.24",
"@fortawesome/react-fontawesome": "^0.2.2",
"@fortawesome/react-fontawesome": "^0.2.2",
"@ramonak/react-progress-bar": "^5.2.0",
"@tempfix/idb": "^8.0.3",
"@testing-library/jest-dom": "^6.5.0",
Expand Down Expand Up @@ -38,7 +40,7 @@
"react-router-dom": "^6.16.0",
"react-scripts": "^5.0.1",
"replace-module-webpack-plugin": "^1.0.0",
"spv-store": "^0.1.30",
"spv-store": "^0.1.44",
"stream-browserify": "^3.0.0",
"styled-components": "^6.0.8",
"ts-loader": "^9.5.1",
Expand Down
2 changes: 1 addition & 1 deletion public/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"manifest_version": 3,
"name": "Yours Wallet",
"description": "A non-custodial and open-source wallet for BSV and 1Sat Ordinals",
"permissions": ["storage", "unlimitedStorage", "tabs"],
"permissions": ["storage", "unlimitedStorage", "tabs", "notifications"],
"action": {
"default_popup": "index.html",
"default_title": "Yours Wallet"
Expand Down
24 changes: 24 additions & 0 deletions src/api/faucet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import axios from 'axios';

const WHATSONCHAIN_API_URL = 'https://api.whatsonchain.com/v1/bsv/test';
const WITNESSONCHAIN_API_URL = 'https://witnessonchain.com/v1';

interface FaucetResponse {
code: number;
message: string;
raw: string;
txid: string;
}

export async function requestTestnetCoins(address: string): Promise<FaucetResponse> {
try {
const response = await axios.post<FaucetResponse>(`${WITNESSONCHAIN_API_URL}/faucet/tbsv`, {
address,
channel: 'yours-wallet',
});
return response.data;
} catch (error) {
console.error('Error requesting testnet coins:', error);
throw error;
}
}
11 changes: 10 additions & 1 deletion src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import {
} from './inject';
import { EncryptResponse } from './pages/requests/EncryptRequest';
import { DecryptResponse } from './pages/requests/DecryptRequest';
import { removeWindow } from './utils/chromeHelpers';
import { removeWindow, sendTransactionNotification } from './utils/chromeHelpers';
import { GetSignaturesResponse } from './pages/requests/GetSignaturesRequest';
import { ChromeStorageObject, ConnectRequest } from './services/types/chromeStorage.types';
import { ChromeStorageService } from './services/ChromeStorage.service';
Expand Down Expand Up @@ -72,6 +72,14 @@ const INACTIVITY_LIMIT = 10 * 60 * 1000; // 10 minutes

// only run in background worker
if (isInServiceWorker) {
const initNewTxsListener = async () => {
const oneSatSPV = await oneSatSPVPromise;
oneSatSPV.events.on('newTxs', (data: number) => {
sendTransactionNotification(data);
});
};
initNewTxsListener();

const processSyncUtxos = async () => {
try {
const oneSatSPV = await oneSatSPVPromise;
Expand Down Expand Up @@ -107,6 +115,7 @@ if (isInServiceWorker) {
chromeStorageService = new ChromeStorageService();
await chromeStorageService.getAndSetStorage();
oneSatSPVPromise = initOneSatSPV(chromeStorageService, isInServiceWorker);
initNewTxsListener();
};

const launchPopUp = () => {
Expand Down
63 changes: 63 additions & 0 deletions src/components/FaucetButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { useState } from 'react';
import { Button } from './Button';
import { useTheme } from '../hooks/useTheme';
import { requestTestnetCoins } from '../api/faucet';
import { useSnackbar } from '../hooks/useSnackbar';
import { ParseMode } from 'spv-store';
import { Transaction } from '@bsv/sdk';
import { useServiceContext } from '../hooks/useServiceContext';

interface FaucetButtonProps {
address: string;
isTestnet: boolean;
onConfirmation: () => void;
}

export function FaucetButton({ address, isTestnet, onConfirmation }: FaucetButtonProps) {
const { theme } = useTheme();
const { addSnackbar } = useSnackbar();
const { oneSatSPV } = useServiceContext();
const [isLoading, setIsLoading] = useState(false);

const handleGetCoins = async () => {
if (!isTestnet) return;

setIsLoading(true);

try {
const response = await requestTestnetCoins(address);

if (response.code === 0) {
const tx = Transaction.fromHex(response.raw);
const res = await oneSatSPV.stores.txos?.ingest(tx, 'faucet', ParseMode.Persist, false);
if (res?.txid) {
onConfirmation();
} else {
addSnackbar('Transaction sent, but not yet confirmed. Please check your balance later.', 'info');
}
} else if (response.code === 20) {
throw new Error('Address still in cooldown. Please wait before requesting again.');
} else {
throw new Error(response.message || 'An unknown error occurred. Please try again later.');
}
} catch (error) {
const errorMessage =
error instanceof Error ? error.message : 'Failed to get testnet coins. Please try again later.';
addSnackbar(errorMessage, 'error');
} finally {
setIsLoading(false);
}
};

if (!isTestnet) return null;

return (
<Button
theme={theme}
type="secondary-outline"
label={isLoading ? 'Requesting...' : 'Get Testnet Coins'}
onClick={handleGetCoins}
disabled={isLoading}
/>
);
}
4 changes: 2 additions & 2 deletions src/components/Ordinal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const OrdinalWrapper = styled.div<OrdinalDivProps>`
background-size: cover;
background-position: center;
background-repeat: no-repeat;
border-radius: 1.25rem;
border-radius: 12%;
cursor: pointer;
border: ${(props) =>
props.selected ? `0.1rem solid ${props.theme.color.component.ordinalSelectedBorder}` : undefined};
Expand All @@ -26,7 +26,7 @@ const OrdinalWrapper = styled.div<OrdinalDivProps>`
const StyledIFrame = styled.iframe<{ size?: string }>`
height: ${(props) => props.size ?? '6.5rem'};
width: ${(props) => props.size ?? '6.5rem'};
border-radius: 1.25rem;
border-radius: 12%;
border: none;
cursor: pointer;
pointer-events: none;
Expand Down
Loading

0 comments on commit 006af47

Please sign in to comment.