diff --git a/package-lock.json b/package-lock.json
index 9e7a735..c4a48b7 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -100,6 +100,13 @@
"uuid": "dist/bin/uuid"
}
},
+ "node_modules/@algorandfoundation/provider": {
+ "version": "0.0.1",
+ "resolved": "git+ssh://git@github.com/algorandfoundation/wallet-provider-ts.git#28c80f5b9e0259b8e83e65c65d802d8123de9046",
+ "dependencies": {
+ "cbor-x": "^1.6.0"
+ }
+ },
"node_modules/@ampproject/remapping": {
"version": "2.2.1",
"dev": true,
@@ -2075,6 +2082,78 @@
"dev": true,
"license": "MIT"
},
+ "node_modules/@cbor-extract/cbor-extract-darwin-arm64": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-arm64/-/cbor-extract-darwin-arm64-2.2.0.tgz",
+ "integrity": "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@cbor-extract/cbor-extract-darwin-x64": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-x64/-/cbor-extract-darwin-x64-2.2.0.tgz",
+ "integrity": "sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@cbor-extract/cbor-extract-linux-arm": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm/-/cbor-extract-linux-arm-2.2.0.tgz",
+ "integrity": "sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==",
+ "cpu": [
+ "arm"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@cbor-extract/cbor-extract-linux-arm64": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm64/-/cbor-extract-linux-arm64-2.2.0.tgz",
+ "integrity": "sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@cbor-extract/cbor-extract-linux-x64": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-x64/-/cbor-extract-linux-x64-2.2.0.tgz",
+ "integrity": "sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@cbor-extract/cbor-extract-win32-x64": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-win32-x64/-/cbor-extract-win32-x64-2.2.0.tgz",
+ "integrity": "sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==",
+ "cpu": [
+ "x64"
+ ],
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
"node_modules/@colors/colors": {
"version": "1.5.0",
"dev": true,
@@ -7745,6 +7824,35 @@
"node": ">=6.0.0"
}
},
+ "node_modules/cbor-extract": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cbor-extract/-/cbor-extract-2.2.0.tgz",
+ "integrity": "sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==",
+ "hasInstallScript": true,
+ "optional": true,
+ "dependencies": {
+ "node-gyp-build-optional-packages": "5.1.1"
+ },
+ "bin": {
+ "download-cbor-prebuilds": "bin/download-prebuilds.js"
+ },
+ "optionalDependencies": {
+ "@cbor-extract/cbor-extract-darwin-arm64": "2.2.0",
+ "@cbor-extract/cbor-extract-darwin-x64": "2.2.0",
+ "@cbor-extract/cbor-extract-linux-arm": "2.2.0",
+ "@cbor-extract/cbor-extract-linux-arm64": "2.2.0",
+ "@cbor-extract/cbor-extract-linux-x64": "2.2.0",
+ "@cbor-extract/cbor-extract-win32-x64": "2.2.0"
+ }
+ },
+ "node_modules/cbor-x": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/cbor-x/-/cbor-x-1.6.0.tgz",
+ "integrity": "sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg==",
+ "optionalDependencies": {
+ "cbor-extract": "^2.2.0"
+ }
+ },
"node_modules/chalk": {
"version": "4.1.2",
"license": "MIT",
@@ -12732,6 +12840,20 @@
"node": "^12.13 || ^14.13 || >=16"
}
},
+ "node_modules/node-gyp-build-optional-packages": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz",
+ "integrity": "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==",
+ "optional": true,
+ "dependencies": {
+ "detect-libc": "^2.0.1"
+ },
+ "bin": {
+ "node-gyp-build-optional-packages": "bin.js",
+ "node-gyp-build-optional-packages-optional": "optional.js",
+ "node-gyp-build-optional-packages-test": "build-test.js"
+ }
+ },
"node_modules/node-gyp/node_modules/rimraf": {
"version": "3.0.2",
"license": "ISC",
@@ -17165,7 +17287,8 @@
"version": "0.0.1",
"license": "MIT",
"dependencies": {
- "@algorandfoundation/liquid-client": "github:algorandfoundation/liquid-auth-js#chore/switch-request-id-to-uuid",
+ "@algorandfoundation/liquid-client": "github:algorandfoundation/liquid-auth-js",
+ "@algorandfoundation/provider": "github:algorandfoundation/wallet-provider-ts",
"@emotion/react": "^11.11.3",
"@emotion/server": "^11.11.0",
"@emotion/styled": "^11.11.0",
@@ -17173,6 +17296,7 @@
"@mui/material": "^5.15.4",
"@tanstack/react-query": "^5.20.5",
"@tanstack/react-query-devtools": "^5.20.5",
+ "cbor-x": "^1.6.0",
"qr-code-styling": "^1.6.0-rc.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
diff --git a/sites/dapp-ui/.eslintrc.cjs b/sites/dapp-ui/.eslintrc.cjs
index 137bb37..74e31c0 100644
--- a/sites/dapp-ui/.eslintrc.cjs
+++ b/sites/dapp-ui/.eslintrc.cjs
@@ -11,6 +11,7 @@ module.exports = {
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
+ '@typescript-eslint/no-explicit-any': 'warn',
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
diff --git a/sites/dapp-ui/package.json b/sites/dapp-ui/package.json
index 18c0516..7ce307b 100644
--- a/sites/dapp-ui/package.json
+++ b/sites/dapp-ui/package.json
@@ -12,7 +12,8 @@
"lint": "eslint \"{src,apps,libs,test}/**/*.{ts,tsx}\" --fix"
},
"dependencies": {
- "@algorandfoundation/liquid-client": "github:algorandfoundation/liquid-auth-js#chore/switch-request-id-to-uuid",
+ "@algorandfoundation/provider": "github:algorandfoundation/wallet-provider-ts",
+ "@algorandfoundation/liquid-client": "github:algorandfoundation/liquid-auth-js",
"@emotion/react": "^11.11.3",
"@emotion/server": "^11.11.0",
"@emotion/styled": "^11.11.0",
@@ -20,6 +21,7 @@
"@mui/material": "^5.15.4",
"@tanstack/react-query": "^5.20.5",
"@tanstack/react-query-devtools": "^5.20.5",
+ "cbor-x": "^1.6.0",
"qr-code-styling": "^1.6.0-rc.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
diff --git a/sites/dapp-ui/src/App.tsx b/sites/dapp-ui/src/App.tsx
index 62639b6..2572213 100644
--- a/sites/dapp-ui/src/App.tsx
+++ b/sites/dapp-ui/src/App.tsx
@@ -14,7 +14,7 @@ import { Algodv2 } from 'algosdk';
import { AlgodContext } from '@/hooks';
import { SignalClientContext } from '@/hooks/useSignalClient.ts';
import { LinkMessage, SignalClient } from '@algorandfoundation/liquid-client';
-import { useAddressStore } from '@/store';
+import { useAddressStore } from '@/store.ts';
const queryClient = new QueryClient();
const algod = new Algodv2(
diff --git a/sites/dapp-ui/src/components/ArcMessage.tsx b/sites/dapp-ui/src/components/ArcMessage.tsx
new file mode 100644
index 0000000..f32f03f
--- /dev/null
+++ b/sites/dapp-ui/src/components/ArcMessage.tsx
@@ -0,0 +1,24 @@
+import { MessageState } from "@/store.ts";
+import Card from "@mui/material/Card";
+import { CardHeader } from "@mui/material";
+import Typography from "@mui/material/Typography";
+import CardContent from "@mui/material/CardContent";
+
+export function ArcMessage(state: MessageState) {
+ return (
+
+
+
+
+ {state.status}
+
+
+ {JSON.stringify(state.message)}
+
+
+
+ );
+}
diff --git a/sites/dapp-ui/src/components/MessageCard.tsx b/sites/dapp-ui/src/components/MessageCard.tsx
deleted file mode 100644
index 34d5e70..0000000
--- a/sites/dapp-ui/src/components/MessageCard.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import Card from '@mui/material/Card';
-import CardContent from '@mui/material/CardContent';
-import Typography from '@mui/material/Typography';
-import { Message } from '@/store.ts';
-import { CardHeader } from '@mui/material';
-
-export function MessageCard({ msg }: { msg: Message }) {
- let message;
- const isLocal = msg.type === 'local';
- switch (msg.data.type) {
- case 'credential':
- message = isLocal
- ? `🔑 Credential Sent: ${msg.data.id}`
- : `🔑 Credential Received: ${msg.data.id}`;
- break;
- case 'transaction':
- message = isLocal
- ? `🚚 Transaction Sent: ${msg.data.txId}`
- : `🚚 Transaction Received: ${msg.data.txId}`;
- break;
- case 'transaction-signature':
- message = isLocal
- ? `🔏 Signature Sent: ${msg.data.txId}`
- : `🔏 Signature Received: ${msg.data.txId}`;
- break;
- default:
- message = 'Unknown message';
- }
- return (
-
-
-
- Message
-
-
-
-
- {message}
-
-
-
- );
-}
diff --git a/sites/dapp-ui/src/components/TransactionCard.tsx b/sites/dapp-ui/src/components/TransactionCard.tsx
deleted file mode 100644
index a1b01f5..0000000
--- a/sites/dapp-ui/src/components/TransactionCard.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-import Card from '@mui/material/Card';
-import { LiquidTransaction } from '@/store.ts';
-import { CardHeader, Link } from '@mui/material';
-
-export function TransactionCard({ txn }: { txn: LiquidTransaction }) {
- const isLive = txn.status === 'confirmed';
- let emoji;
- switch (txn.status) {
- case 'confirmed':
- emoji = '✅';
- break;
- case 'submitted':
- emoji = '🔵';
- break;
- case 'failed':
- emoji = '❌';
- break;
- default:
- emoji = '🟡';
- }
- return (
-
-
- {txn.txn.txID()}
-
- ) : (
- txn.txn.txID()
- )
- }
- >
-
- );
-}
diff --git a/sites/dapp-ui/src/entry-main.tsx b/sites/dapp-ui/src/entry-main.tsx
index f6db3f5..f3133a6 100644
--- a/sites/dapp-ui/src/entry-main.tsx
+++ b/sites/dapp-ui/src/entry-main.tsx
@@ -2,7 +2,6 @@ import './index.css';
import * as ReactDOM from 'react-dom/client';
// import { StrictMode } from 'react';
import App from './App.tsx';
-
ReactDOM.createRoot(document.getElementById('root')!).render(
//
,
diff --git a/sites/dapp-ui/src/hooks/useDataChannel.ts b/sites/dapp-ui/src/hooks/useDataChannel.ts
index 3d37cd4..10082e9 100644
--- a/sites/dapp-ui/src/hooks/useDataChannel.ts
+++ b/sites/dapp-ui/src/hooks/useDataChannel.ts
@@ -7,12 +7,17 @@ import { SignalClientContext } from '@/hooks/useSignalClient.ts';
*/
export function useDataChannel(onMessage?: (event: MessageEvent) => void) {
const { dataChannel } = useContext(SignalClientContext);
+ function onError(...args: any[]) {
+ console.error('Data channel error', args);
+ }
useEffect(() => {
if (!dataChannel || !onMessage) return;
dataChannel.addEventListener('message', onMessage);
+ dataChannel.addEventListener('error', onError)
return () => {
dataChannel.removeEventListener('message', onMessage);
- };
+ dataChannel.removeEventListener('error', onError);
+ }
}, [dataChannel, onMessage]);
return dataChannel;
diff --git a/sites/dapp-ui/src/hooks/useSignalClient.ts b/sites/dapp-ui/src/hooks/useSignalClient.ts
index f75f163..e5322b4 100644
--- a/sites/dapp-ui/src/hooks/useSignalClient.ts
+++ b/sites/dapp-ui/src/hooks/useSignalClient.ts
@@ -8,6 +8,8 @@ type SignalClientState = {
setStatus: (_: 'connected' | 'disconnected') => void;
dataChannel: RTCDataChannel | null;
setDataChannel: (_: RTCDataChannel | null) => void;
+ loading: boolean;
+ setLoading: (_: boolean) => void;
};
export const SignalClientContext = createContext({
client: null,
diff --git a/sites/dapp-ui/src/lib/provider.ts b/sites/dapp-ui/src/lib/provider.ts
new file mode 100644
index 0000000..440fca5
--- /dev/null
+++ b/sites/dapp-ui/src/lib/provider.ts
@@ -0,0 +1,21 @@
+import {decode} from 'cbor-x'
+import { decodeUnsignedTransaction } from "algosdk";
+import { IARC0001Transaction, ResponseMessage, Results, fromBase64Url } from "@algorandfoundation/provider";
+
+export function attachEncodedSignature(address: string, txn: string, signature: string){
+ return decodeUnsignedTransaction(fromBase64Url(txn))
+ .attachSignature(address, fromBase64Url(signature));
+}
+
+export function attachSignedTransactionsFromResult(address: string, result: Results, txns: IARC0001Transaction[]){
+ let stxns = [];
+ for(let i = 0; i < txns.length; i++){
+ stxns.push(attachEncodedSignature(address, txns[i].txn, result.stxns[i]!!))
+ }
+ return stxns
+}
+
+export function fromResult(result: string): ResponseMessage {
+ return decode(fromBase64Url(result)) as ResponseMessage
+}
+
diff --git a/sites/dapp-ui/src/pages/connected.tsx b/sites/dapp-ui/src/pages/connected.tsx
index c9d41f2..7645571 100644
--- a/sites/dapp-ui/src/pages/connected.tsx
+++ b/sites/dapp-ui/src/pages/connected.tsx
@@ -1,81 +1,136 @@
-import { useDataChannel } from '@/hooks/useDataChannel.ts';
-import { useEffect, useState } from 'react';
+import { useEffect, useMemo, useState } from "react";
+import Box from '@mui/material/Box'
+import Input from '@mui/material/Input'
+import LinearProgress from '@mui/material/LinearProgress'
+import Paper from '@mui/material/Paper'
+import Slider from '@mui/material/Slider'
import Button from '@mui/material/Button';
+import FormControl from '@mui/material/FormControl';
+import Typography from '@mui/material/Typography';
+import { useNavigate } from 'react-router-dom';
+
import {
+ // TODO: Migrate to algo-models
encodeUnsignedTransaction,
+ // TODO: Migrate to algo-fetch
waitForConfirmation,
+ // TODO: Migrate to algo-models
makePaymentTxnWithSuggestedParamsFromObject,
} from 'algosdk';
-import { toBase64URL, fromBase64Url } from '@algorandfoundation/liquid-client';
+
+import { RequestMessage, toSignTransactionsParamsRequestMessage, toBase64URL } from "@algorandfoundation/provider";
+import { SignalClient } from "@algorandfoundation/liquid-client";
+import {
+ attachSignedTransactionsFromResult,
+ fromResult,
+} from "@/lib/provider.js";
+
+import { EmptyAccountCard } from '@/components/EmptyAccountCard.tsx';
+import { ArcMessage } from "@/components/ArcMessage.tsx";
+
+import { useDataChannel } from '@/hooks/useDataChannel.ts';
import { useAlgod } from '@/hooks/useAlgod.ts';
import { useAccountInfo } from '@/hooks/useAccountInfo.ts';
-import FormControl from '@mui/material/FormControl';
-import { Box, Input, Paper, Slider } from '@mui/material';
-import Typography from '@mui/material/Typography';
+
import {
- useAddressStore,
- useMessageStore,
- useTransactionStore,
-} from '../store.ts';
-import { useNavigate } from 'react-router-dom';
-import { MessageCard } from '@/components/MessageCard.tsx';
-import { TransactionCard } from '@/components/TransactionCard.tsx';
-import { EmptyAccountCard } from '@/components/EmptyAccountCard.tsx';
+ useAddressStore, useARC27MessageStore,
+} from "@/store.ts";
+
export function ConnectedPage() {
const navigate = useNavigate();
+
+ // Algorand Specific State
const algod = useAlgod();
+ // TODO: migrate to Use-Wallet-Liquid
const wallet = useAddressStore((state) => state.address);
+ const [suggestedParams, setSuggestedParams] = useState(null)
+ // Account
const accountInfo = useAccountInfo(wallet, 3000);
+
+ // Payment Transaction Form
const [from, setFrom] = useState(wallet);
const [to, setTo] = useState(wallet);
const [amount, setAmount] = useState(0);
+ const [count, setCount] = useState(1);
+
+ // Sending indicator
+ const [progress, setProgress] = useState(0);
+ const [buffer, setBuffer] = useState(0);
+
+ // Message Store
+ const addArcMessage = useARC27MessageStore((state) => state.addMessage);
+ const arcMessages = useARC27MessageStore((state) => state.messages);
+ const updateArcMessage = useARC27MessageStore((state) => state.updateMessage);
- const addMessage = useMessageStore((state) => state.addMessage);
- const messages = useMessageStore((state) => state.messages);
- const addTransaction = useTransactionStore((state) => state.addTransaction);
- const updateTransaction = useTransactionStore(
- (state) => state.updateTransaction,
- );
- const transactions = useTransactionStore((state) => state.transactions);
// Receive response
const datachannel = useDataChannel((event) => {
- const message = JSON.parse(event.data);
- // TODO: Handle P2P using a previously known credential
- //if (message.type === 'credential') localStorage['credId'] = message.id;
- if (message.type !== 'transaction-signature') return;
- addMessage({
- type: 'remote',
- data: JSON.parse(event.data),
- timestamp: Date.now(),
- });
async function handleMessage() {
- const message = JSON.parse(event.data);
- if (message.type === 'credential') localStorage['credId'] = message.id;
- if (message.type !== 'transaction-signature') return;
- const txn = transactions.find((txn) => txn.txId === message.txId);
- if (!txn) return;
- const sig = fromBase64Url(message.sig);
- const signedTxn = txn.txn.attachSignature(
- accountInfo.data?.['auth-addr']
- ? accountInfo.data?.['auth-addr']
- : wallet,
- sig,
- );
- updateTransaction(txn.txId, 'signed');
- const { txId } = await algod.sendRawTransaction(signedTxn).do();
- updateTransaction(txn.txId, 'submitted');
- await waitForConfirmation(algod, txId, 4);
- updateTransaction(txn.txId, 'confirmed');
+ try{
+ // Ignore JSON messages
+ JSON.parse(event.data);
+ } catch (e) {
+
+ // Fetch ResultMessage from the encoded string
+ let data = fromResult(event.data);
+ // Add the incoming message
+ addArcMessage({status: 'received', message: data})
+ // Get matching request
+ const matchingRequests = arcMessages.filter((msg) => msg.message.id === data.requestId)
+ if(matchingRequests.length !== 1) throw new Error('Invalid request')
+ const request = matchingRequests[0]
+ updateArcMessage(request.message.id, 'received')
+
+ // Get the transaction strings
+ const msgTxns = (request.message as RequestMessage).params.txns
+
+ // Attach the signatures
+ let stxns = attachSignedTransactionsFromResult(wallet, data.result, msgTxns)
+ updateArcMessage(request.message.id, 'signed');
+
+ const confirmationPromises = await batchSignTransactions(stxns)
+ updateArcMessage(request.message.id, 'submitted');
+ await Promise.all(confirmationPromises)
+ setProgress(0)
+ setBuffer(0)
+ updateArcMessage(request.message.id, 'confirmed');
+ }
+
+ }
+ async function batchSignTransactions(stxns: Uint8Array[]) {
+ let confirmationPromises = [];
+ for (let i = 0; i < stxns.length; i++) {
+ const { txId } = await algod.sendRawTransaction(stxns[i]).do();
+ setBuffer((i+1)/stxns.length * 100)
+ confirmationPromises.push(waitForConfirmation(algod, txId, 4).then(()=>{
+ setProgress((i+1)/stxns.length * 100)
+ }));
+ }
+ return confirmationPromises
}
handleMessage();
});
+ // Redirect when there is no datachannel or wallet
useEffect(() => {
if (!datachannel || wallet === '') navigate('/');
}, [datachannel, wallet, navigate]);
+ // Load Suggested Params
+ useEffect(()=>{
+ algod.getTransactionParams().do().then((params)=>{
+ setSuggestedParams(params)
+ });
+ }, [])
+
+ // Max Account Spend
+ const maxSpend = useMemo(()=>{
+ if(typeof accountInfo.data === 'undefined' || !suggestedParams) return 0;
+ const txnCost = (amount + suggestedParams.minFee) * count;
+ return Math.round(accountInfo.data.amount / txnCost)
+ }, [count, accountInfo.data, suggestedParams])
+
if (accountInfo.data && accountInfo.data.amount === 0) {
return ;
}
@@ -107,13 +162,27 @@ export function ConnectedPage() {
setAmount(value as number)}
/>
+
+
+ Amount of Transactions
+
+ setCount(value as number)}
+ />
+
+
- Transactions
+ ARC27 Messages
-
- {transactions.map((transaction, i) => (
-
- ))}
-
-
- Messages
-
-
- {messages.map((message, i) => (
-
- ))}
-
+
+
+ {arcMessages.map((message, i) => (
+
+ ))}
+
>
);
}
diff --git a/sites/dapp-ui/src/store.ts b/sites/dapp-ui/src/store.ts
index ffd89a2..c70d9dc 100644
--- a/sites/dapp-ui/src/store.ts
+++ b/sites/dapp-ui/src/store.ts
@@ -1,6 +1,6 @@
import { create } from 'zustand';
import { persist } from 'zustand/middleware';
-import { Transaction } from 'algosdk';
+import { RequestMessage, ResponseMessage } from "@algorandfoundation/algo-models/provider";
interface AddressState {
address: string;
@@ -22,88 +22,29 @@ export const useAddressStore = create<
),
);
-export type TransactionSignaturePayload = {
- type: 'transaction-signature';
- txId: string;
- sig: string;
-};
-export type TransactionPayload = {
- type: 'transaction';
- txId: string;
- txn: string;
-};
-// {
-// "address": "PNNMCGV3XLEDFEGR7IHSGY5HHGAQQ4OC7H75SPGQUFVTNWV45JVXPRJULY",
-// "device": "Pixel 8 Pro",
-// "origin": "https://catfish-pro-wolf.ngrok-free.app",
-// "id": "AdoMGSqp-ni0udT2e5RafkSJo2Czs0s-Ekr5wB06PIpXIhlG-qfdCyN_riM_enKwZnwQXwrFp3e9IB0VNLg6swM",
-// "prevCounter": 2,
-// "type": "credential"
-// }
-export type CredentialPayload = {
- type: 'credential';
- id: string;
- address: string;
- device?: string;
- origin: string;
- prevCounter: number;
-};
-
-export type MessagePayload = {
- type: 'transaction' | 'credential' | 'transaction-signature';
- // data: TransactionSignature | ;
-};
-export type Message = {
- data:
- | TransactionPayload
- | TransactionSignaturePayload
- | CredentialPayload
- | string;
- type: 'local' | 'remote';
- timestamp: number;
-};
-
-interface MessageStore {
- messages: Message[];
- addMessage: (message: Message) => void;
- clearMessages: () => void;
+export type MessageState = {
+ status: 'created' | 'sent' | 'received' | 'signed' | 'submitted' | 'confirmed' | 'failed';
+ message: RequestMessage | ResponseMessage
}
-export const useMessageStore = create((set) => ({
- messages: [],
- addMessage: (message: Message) =>
- set((state) => ({ messages: [...state.messages, message] })),
- clearMessages: () => set({ messages: [] }),
-}));
-
-export type LiquidTransaction = {
- txn: Transaction;
- txId: string;
- sig?: string;
- status: 'created' | 'sent' | 'signed' | 'submitted' | 'confirmed' | 'failed';
-};
-
-interface TransactionStore {
- transactions: LiquidTransaction[];
- addTransaction: (txn: LiquidTransaction) => void;
- updateTransaction: (
- txId: string,
- status: LiquidTransaction['status'],
- ) => void;
- clearTransactions: () => void;
+export interface ARC27MessageStore {
+ messages: MessageState[];
+ addMessage: (state: MessageState) => void;
+ updateMessage: (id: string, status: MessageState['status']) => void;
+ clearMessages: () => void;
}
-export const useTransactionStore = create((set) => ({
- transactions: [],
- addTransaction: (txn: LiquidTransaction) =>
- set((state) => ({ transactions: [...state.transactions, txn] })),
- updateTransaction: (txId: string, status: LiquidTransaction['status']) =>
- set((state) => ({
- transactions: state.transactions.map((txn) => {
- if (txn.txId === txId) {
- return { ...txn, status };
- }
- return txn;
- }),
- })),
- clearTransactions: () => set({ transactions: [] }),
+export const useARC27MessageStore = create((set) => ({
+ messages: [],
+ addMessage: (msg: MessageState) => set((state) => ({ messages: [...state.messages, msg] })),
+ updateMessage: (id: string, status: MessageState['status']) =>
+ set((state) => ({
+ messages: state.messages.map((msg) => {
+ if (msg.message.id === id) {
+ return { ...msg, status };
+ }
+ return msg;
+ }),
+ }),
+ ),
+ clearMessages: () => set({ messages: [] }),
}));
diff --git a/sites/dapp-ui/vite.config.ts b/sites/dapp-ui/vite.config.ts
index 2070be9..c4842b9 100644
--- a/sites/dapp-ui/vite.config.ts
+++ b/sites/dapp-ui/vite.config.ts
@@ -5,8 +5,8 @@ import { ViteImageOptimizer } from 'vite-plugin-image-optimizer';
import react from '@vitejs/plugin-react-swc';
import { resolve } from 'node:path';
-const DEFAULT_PROXY_URL = 'http://localhost:3000';
-const DEFAULT_WSS_PROXY_URL = 'ws://localhost:3000';
+const DEFAULT_PROXY_URL = 'http://192.168.1.17:5173';
+const DEFAULT_WSS_PROXY_URL = 'ws://192.168.1.17:5173';
export default defineConfig({
server: {
@@ -27,7 +27,8 @@ export default defineConfig({
'@/components': resolve(__dirname, 'src', 'components'),
'@/hooks': resolve(__dirname, 'src', 'hooks'),
'@/pages': resolve(__dirname, 'src', 'pages'),
- '@/store': resolve(__dirname, 'src', 'store'),
+ '@/store.ts': resolve(__dirname, 'src', 'store.ts'),
+ '@/lib': resolve(__dirname, 'src', 'lib'),
},
},
plugins: [
@@ -85,7 +86,7 @@ export default defineConfig({
],
},
}),
- splitVendorChunkPlugin(),
+ // splitVendorChunkPlugin(),
ViteImageOptimizer(),
react(),
],