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
15 changes: 12 additions & 3 deletions examples/secp-ui/src/components/PasskeySwig.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ import {
SystemProgram,
Transaction,
} from '@solana/web3.js';
import { AuthorityType, getSignInstructions, Role } from '@swig-wallet/classic';
import {
AuthorityType,
getSignInstructions,
getSwigWalletAddress,
Role,
} from '@swig-wallet/classic';
import { useState } from 'react';
import { toast } from 'sonner';
import { GoToExplorer } from './GoToExplorer';
Expand Down Expand Up @@ -102,13 +107,15 @@ export function PasskeySwig() {

let capturedSignatureData: StoredSignatureData | null = null;

const walletAddress = await getSwigWalletAddress(swig);

const ixs = await getSignInstructions(
swig,
signerRole.id,
[
SystemProgram.transfer({
lamports: 0.1 * LAMPORTS_PER_SOL,
fromPubkey: swigAddress!,
fromPubkey: walletAddress,
toPubkey: Keypair.generate().publicKey,
}),
],
Expand Down Expand Up @@ -210,13 +217,15 @@ export function PasskeySwig() {
(currentRole.authority as any).odometer?.(),
);

const replayWalletAddress = await getSwigWalletAddress(swig);

const ixs = await getSignInstructions(
swig,
currentRole.id,
[
SystemProgram.transfer({
lamports: 0.1 * LAMPORTS_PER_SOL,
fromPubkey: swigAddress!,
fromPubkey: replayWalletAddress,
toPubkey: Keypair.generate().publicKey,
}),
],
Expand Down
43 changes: 35 additions & 8 deletions examples/secp-ui/src/hooks/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
getCreateSwigInstruction,
getEvmPersonalSignPrefix,
getSignInstructions,
getSwigWalletAddress,
} from '@swig-wallet/classic';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
Expand Down Expand Up @@ -64,6 +65,26 @@ export function useSwig() {
return { swig: query.data, ...query };
}

/**
* In Swig v3 the swig PDA holds roles/authorities while a separate
* "wallet" PDA holds the actual SOL/tokens and is the address the program
* `invoke_signed`s for. Use this for airdrops, balance reads, and as the
* `fromPubkey` of any inner transfer instruction.
*/
export function useSwigWalletAddress() {
const { swig } = useSwig();
const { swigAddress } = getSwigAddress();

const query = useQuery({
queryKey: ['swig', 'walletAddress', swigAddress.toBase58()],
queryFn: () => getSwigWalletAddress(swig!),
enabled: !!swig,
staleTime: Infinity,
});

return { walletAddress: query.data, ...query };
}

export function useWalletPublicKey() {
const { signMessageAsync } = useSignMessage();
const { address } = useAccount();
Expand Down Expand Up @@ -144,29 +165,31 @@ export function useCreateSwig() {

export function useSwigBalance() {
const { connection } = useConnection();
const { swigAddress } = getSwigAddress();
const { walletAddress } = useSwigWalletAddress();

const query = useQuery({
queryKey: ['swig', 'balance'],
queryFn: () => connection.getBalance(swigAddress, 'processed'),
queryKey: ['swig', 'balance', walletAddress?.toBase58()],
queryFn: () => connection.getBalance(walletAddress!, 'processed'),
enabled: !!walletAddress,
refetchInterval: 3 * 1000,
});

return { swigBalance: query.data, ...query };
}

export function useSwigTransfer() {
const { swigAddress } = getSwigAddress();
const { connection } = useConnection();
const queryClient = useQueryClient();
const { address } = useAccount();
const { swig } = useSwig();
const { walletAddress } = useSwigWalletAddress();
const { signMessageAsync } = useSignMessage();

const mutation = useMutation({
mutationFn: async () => {
if (!address) throw new Error('Wallet not connected');
if (!swig) throw new Error('Swig not created');
if (!walletAddress) throw new Error('Swig wallet address not ready yet');
let signerRoles = swig.findRolesBySecp256k1SignerAddress(address);
if (!signerRoles)
throw new Error(`No roles found from wallet address ${address}`);
Expand All @@ -177,7 +200,7 @@ export function useSwigTransfer() {
[
SystemProgram.transfer({
lamports: 0.1 * LAMPORTS_PER_SOL,
fromPubkey: swigAddress,
fromPubkey: walletAddress,
toPubkey: Keypair.generate().publicKey,
}),
],
Expand Down Expand Up @@ -225,14 +248,18 @@ export function useSwigTransfer() {
}

export function useRequestAirdrop() {
const { swigAddress } = getSwigAddress();
const { walletAddress } = useSwigWalletAddress();
const { connection } = useConnection();
const queryClient = useQueryClient();
const {} = useSwigBalance();

const mutation = useMutation({
mutationFn: async () =>
connection.requestAirdrop(swigAddress, LAMPORTS_PER_SOL * 100),
mutationFn: async () => {
if (!walletAddress) {
throw new Error('Swig wallet address not ready yet');
}
return connection.requestAirdrop(walletAddress, LAMPORTS_PER_SOL * 100);
},
onSuccess: (tx) => {
toast.success('Transaction successful!', {
action: <GoToExplorer tx={tx} />,
Expand Down
5 changes: 4 additions & 1 deletion examples/secp-ui/src/hooks/passkey.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
fetchSwig,
getCreateSwigInstruction,
getSignInstructions,
getSwigWalletAddress,
} from '@swig-wallet/classic';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { toast } from 'sonner';
Expand Down Expand Up @@ -212,13 +213,15 @@ export function useSwigTransferWithPasskey() {
);
}

const walletAddress = await getSwigWalletAddress(swig);

const ixs = await getSignInstructions(
swig,
role.id,
[
SystemProgram.transfer({
lamports: 0.1 * LAMPORTS_PER_SOL,
fromPubkey: swigAddress,
fromPubkey: walletAddress,
toPubkey: Keypair.generate().publicKey,
}),
],
Expand Down