From 9b7391677cba9a99108006294bceb270e50b5624 Mon Sep 17 00:00:00 2001 From: thesn10 <38666407+thesn10@users.noreply.github.com> Date: Sat, 23 May 2026 14:45:49 +0200 Subject: [PATCH] update app to use solana kit --- app/.gitignore | 1 + app/package.json | 3 +- app/src/app/page.tsx | 4 +- app/src/components/CreateEscrowForm.tsx | 101 ++++++++++-------- app/src/components/EscrowCard.tsx | 13 +-- app/src/components/EscrowDetail.tsx | 133 +++++++++++++----------- app/src/components/ResolverPanel.tsx | 110 +++++++++++--------- app/src/hooks/useEscrowDetail.ts | 37 +++---- app/src/hooks/useEscrows.ts | 31 ++---- app/tsconfig.json | 2 +- sdk/src/index.ts | 43 +++++++- sdk/src/registry.ts | 50 ++++++++- yarn.lock | 48 +-------- 13 files changed, 320 insertions(+), 256 deletions(-) diff --git a/app/.gitignore b/app/.gitignore index 33600ed..dc1f287 100644 --- a/app/.gitignore +++ b/app/.gitignore @@ -2,3 +2,4 @@ node_modules/ public/tamagui.generated.css .env*.local +tsconfig.tsbuildinfo \ No newline at end of file diff --git a/app/package.json b/app/package.json index 1c7f159..16eb775 100644 --- a/app/package.json +++ b/app/package.json @@ -7,10 +7,9 @@ "start": "next start" }, "dependencies": { - "@coral-xyz/anchor": "^0.32.1", "@descro/sdk": "workspace:*", "@solana/connector": "^0.2.4", - "@solana/web3.js": "^1.98.4", + "@solana/kit": "^6.0.0", "@tamagui/config": "^2.0.0-rc.42", "@tamagui/next-theme": "^2.0.0-rc.42", "next": "^16.2.6", diff --git a/app/src/app/page.tsx b/app/src/app/page.tsx index b0a7070..c32f434 100644 --- a/app/src/app/page.tsx +++ b/app/src/app/page.tsx @@ -124,9 +124,9 @@ export default function PlaygroundPage() { {escrows.map((item) => ( setSelected(item)} /> ))} diff --git a/app/src/components/CreateEscrowForm.tsx b/app/src/components/CreateEscrowForm.tsx index a40f5ea..90b6ba9 100644 --- a/app/src/components/CreateEscrowForm.tsx +++ b/app/src/components/CreateEscrowForm.tsx @@ -1,21 +1,32 @@ 'use client' -import { useState, useMemo } from 'react' +import { useState } from 'react' import { YStack, XStack, Text, Button, Input, Spinner } from 'tamagui' -import { PublicKey, Transaction, Connection } from '@solana/web3.js' -import { AnchorProvider } from '@coral-xyz/anchor' -import { useTransactionSigner, useDisconnectWallet, useCluster } from '@solana/connector/react' -import { useWalletAdapterCompat } from '@solana/connector/compat' -import BN from 'bn.js' -import { EscrowClient } from '@descro/sdk' +import { + createSolanaRpc, + createSolanaRpcSubscriptions, + pipe, + createTransactionMessage, + setTransactionMessageFeePayerSigner, + setTransactionMessageLifetimeUsingBlockhash, + appendTransactionMessageInstructions, + signTransactionMessageWithSigners, + sendAndConfirmTransactionFactory, + assertIsTransactionWithBlockhashLifetime, + getSignatureFromTransaction, + address as kitAddress, +} from '@solana/kit' +import { useKitTransactionSigner, useWallet, useCluster } from '@solana/connector/react' +import { getCreateEscrowInstructionAsync } from '@descro/sdk' +import type { Address } from '@descro/sdk' -function getNextEscrowId(walletPubkey: string): BN { - const key = `descro_escrow_id_${walletPubkey}` +function getNextEscrowId(walletAddress: string): bigint { + const key = `descro_escrow_id_${walletAddress}` const stored = localStorage.getItem(key) const current = stored ? parseInt(stored, 10) : 0 const next = current + 1 localStorage.setItem(key, next.toString()) - return new BN(next) + return BigInt(next) } interface CreateEscrowFormProps { @@ -23,17 +34,10 @@ interface CreateEscrowFormProps { } export function CreateEscrowForm({ onCreated }: CreateEscrowFormProps) { - const { signer } = useTransactionSigner() - const { disconnect } = useDisconnectWallet() + const { signer } = useKitTransactionSigner() + const { account: address } = useWallet() const { cluster } = useCluster() - const walletAdapter = useWalletAdapterCompat(signer, disconnect) - - const connection = useMemo( - () => (cluster?.url ? new Connection(cluster.url, 'confirmed') : null), - [cluster?.url], - ) - - const publicKey = walletAdapter.publicKey ? new PublicKey(walletAdapter.publicKey.toString()) : null + const rpcUrl = cluster?.url ?? null const [buyer, setBuyer] = useState('') const [amountSol, setAmountSol] = useState('') @@ -47,29 +51,30 @@ export function CreateEscrowForm({ onCreated }: CreateEscrowFormProps) { setError(null) setSuccess(null) - if (!publicKey || !connection) { + if (!signer || !address || !rpcUrl) { setError('Connect your wallet first.') return } - let buyerPk: PublicKey + let buyerAddress: Address try { - buyerPk = new PublicKey(buyer) + buyerAddress = kitAddress(buyer) } catch { setError('Invalid buyer public key.') return } - const amountLamports = parseFloat(amountSol) - if (isNaN(amountLamports) || amountLamports <= 0) { + const amountSolNum = parseFloat(amountSol) + if (isNaN(amountSolNum) || amountSolNum <= 0) { setError('Invalid SOL amount.') return } + const amountLamports = BigInt(Math.round(amountSolNum * 1e9)) - let resolverPk: PublicKey | null = null + let resolverAddress: Address | null = null if (resolver.trim()) { try { - resolverPk = new PublicKey(resolver.trim()) + resolverAddress = kitAddress(resolver.trim()) } catch { setError('Invalid resolver public key.') return @@ -78,29 +83,33 @@ export function CreateEscrowForm({ onCreated }: CreateEscrowFormProps) { setLoading(true) try { - const provider = new AnchorProvider( - connection, - { publicKey, signTransaction: walletAdapter.signTransaction!.bind(walletAdapter) } as never, - {}, - ) - const client = new EscrowClient(provider) - const escrowId = getNextEscrowId(publicKey.toBase58()) - const amount = new BN(Math.round(amountLamports * 1e9)) + const rpc = createSolanaRpc(rpcUrl) + const rpcSubscriptions = createSolanaRpcSubscriptions(rpcUrl.replace('http', 'ws')) + const escrowId = getNextEscrowId(address) - const ix = await client.buildCreateEscrow({ - seller: publicKey, - buyer: buyerPk, - amount, - disputeResolver: resolverPk, + const ix = await getCreateEscrowInstructionAsync({ + seller: signer, + buyer: buyerAddress, + amount: amountLamports, + disputeResolver: resolverAddress, escrowId, }) - const { blockhash, lastValidBlockHeight } = await connection.getLatestBlockhash() - const tx = new Transaction({ blockhash, lastValidBlockHeight, feePayer: publicKey }).add(ix) - const sig = await walletAdapter.sendTransaction(tx, connection) - await connection.confirmTransaction({ signature: sig, blockhash, lastValidBlockHeight }, 'confirmed') + const { value: latestBlockhash } = await rpc.getLatestBlockhash().send() - setSuccess(`Escrow #${escrowId.toString()} created! Tx: ${sig.slice(0, 16)}…`) + const txMsg = pipe( + createTransactionMessage({ version: 0 }), + (tx) => setTransactionMessageFeePayerSigner(signer, tx), + (tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), + (tx) => appendTransactionMessageInstructions([ix as never], tx), + ) + + const signed = await signTransactionMessageWithSigners(txMsg) + assertIsTransactionWithBlockhashLifetime(signed) + await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(signed, { commitment: 'confirmed' }) + const sig = getSignatureFromTransaction(signed) + + setSuccess(`Escrow #${escrowId} created! Tx: ${sig.slice(0, 16)}…`) setBuyer('') setAmountSol('') setResolver('') @@ -164,7 +173,7 @@ export function CreateEscrowForm({ onCreated }: CreateEscrowFormProps) {