Skip to content

Commit

Permalink
Merge pull request #160 from secretkeylabs/mahmoud/eng-3760CC-transfe…
Browse files Browse the repository at this point in the history
…r-runes-via-sats-connect

runes-transfer-via-sats-connect
  • Loading branch information
m-aboelenein authored Aug 23, 2024
2 parents 53e20e5 + 57115cb commit 13e9eef
Show file tree
Hide file tree
Showing 5 changed files with 157 additions and 32 deletions.
2 changes: 1 addition & 1 deletion example/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions example/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { NetworkSelector } from './components/NetworkSelector';
import { SendSip10 } from './components/stacks/SendSip10';
import { SendStx } from './components/stacks/SendStx';
import { SignTransaction } from './components/stacks/SignTransaction.tsx';
import TransferRunes from './components/transferRunes/index.tsx';
import { WalletType } from './components/wallet/WalletType';
import { useLocalStorage } from './hooks';
import { CollapseDesktop } from './layouts/CollapseDesktop';
Expand Down Expand Up @@ -178,11 +179,12 @@ const BitcoinMethods = () => {
<SignMessage addresses={[...btcAddressInfo]} />
<SendBtc network={network} />
<SendInscription network={network} />
<TransferRunes network={network} />
<GetBtcBalance />
<MintRunes network={network} addresses={[...btcAddressInfo]} />
<EtchRunes network={network} addresses={[...btcAddressInfo]} />
<GetRunesBalance />
<GetInscriptions />
<MintRunes network={network} addresses={[...btcAddressInfo]} />
<EtchRunes network={network} addresses={[...btcAddressInfo]} />
</>
);
};
Expand Down
136 changes: 136 additions & 0 deletions example/src/components/transferRunes/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { useCallback, useMemo, useState } from 'react';
import Wallet, { BitcoinNetworkType } from 'sats-connect';
import { Button, Card, Input, Success } from '../../App.styles';

interface Props {
network: BitcoinNetworkType;
}

interface Recipient {
address: string;
runeName: string;
amount: string;
}

const TransferRunes = ({ network }: Props) => {
const [recipients, setRecipients] = useState<Recipient[]>([
{ address: '', runeName: '', amount: '' },
]);
const [txnId, setTxnId] = useState('');

const addRecipient = () => {
setRecipients([...recipients, { address: '', runeName: '', amount: '' }]);
};

const updateRecipient = (index: number, field: keyof Recipient, value: string) => {
const updatedRecipients = [...recipients];
updatedRecipients[index][field] = value;
setRecipients(updatedRecipients);
};

const removeRecipient = (index: number) => {
if (recipients.length > 1) {
const updatedRecipients = recipients.filter((_, i) => i !== index);
setRecipients(updatedRecipients);
}
};

const onClick = useCallback(() => {
(async () => {
const response = await Wallet.request('runes_transfer', {
recipients,
});

if (response.status === 'error') {
console.error(response.error);
alert('Error sending Runes. See console for details.');
return;
}

setTxnId(response.result.txid);
setRecipients([{ address: '', runeName: '', amount: '' }]);
})().catch(console.error);
}, [recipients]);

const explorerUrl = useMemo(
() =>
network === BitcoinNetworkType.Mainnet
? `https://mempool.space/tx/${txnId}`
: `https://mempool.space/testnet/tx/${txnId}`,
[network, txnId]
);

return (
<Card>
<h3>Send Runes</h3>
{!txnId && (
<>
{recipients.map((recipient, index) => (
<div key={index}>
{index > 0 && <hr />}
<h4>Recipient {index + 1}</h4>
<div>
<div>Rune Name</div>
<Input
type="text"
value={recipient.runeName}
onChange={(e) => updateRecipient(index, 'runeName', e.target.value)}
/>
</div>
<div>
<div>Amount</div>
<Input
type="text"
value={recipient.amount}
onChange={(e) => updateRecipient(index, 'amount', e.target.value)}
/>
</div>
<div>
<div>Address</div>
<Input
type="text"
value={recipient.address}
onChange={(e) => updateRecipient(index, 'address', e.target.value)}
/>
</div>
</div>
))}
<div
style={{
display: 'flex',
gap: 8,
marginTop: 16,
marginBottom: 16,
}}
>
<Button onClick={addRecipient} className="secondary">
Add Recipient
</Button>
{recipients.length > 1 && (
<Button onClick={() => removeRecipient(recipients.length - 1)} className="secondary">
Remove Recipient
</Button>
)}
</div>
<Button
onClick={onClick}
disabled={recipients.some((r) => !r.runeName || !r.amount || !r.address)}
>
Send
</Button>
</>
)}
{txnId && (
<Success>
Success! Click{' '}
<a href={explorerUrl} target="_blank" rel="noreferrer">
here
</a>{' '}
to see your transaction
</Success>
)}
</Card>
);
};

export default TransferRunes;
41 changes: 14 additions & 27 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "sats-connect",
"version": "2.7.0",
"version": "2.8.0",
"main": "dist/index.mjs",
"files": [
"dist"
Expand All @@ -24,7 +24,7 @@
]
},
"dependencies": {
"@sats-connect/core": "0.2.1",
"@sats-connect/core": "0.2.2",
"@sats-connect/make-default-provider-config": "0.0.5",
"@sats-connect/ui": "0.0.6"
},
Expand Down

0 comments on commit 13e9eef

Please sign in to comment.