diff --git a/package.json b/package.json
index 96d5eb8..3a54348 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
+ "@aptos-labs/ts-sdk": "^2.0.1",
"@ethereumjs/common": "^4.3.0",
"@ethereumjs/tx": "^5.3.0",
"@ethereumjs/util": "^9.0.3",
diff --git a/src/App.jsx b/src/App.jsx
index 3df17af..48756b5 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -6,13 +6,14 @@ import { BitcoinView } from './components/Bitcoin';
import { explorerForChain, MPC_CONTRACT, RPCforChain } from './config';
import { useWalletSelector } from '@near-wallet-selector/react-hook';
import { SolanaView } from './components/Solana';
+import { AptosView } from './components/Aptos';
import { XRPView } from './components/XRP';
function App() {
const { signedAccountId } = useWalletSelector();
const [status, setStatus] = useState('Please login to request a signature');
- const [chain, setChain] = useState('eth');
+ const [chain, setChain] = useState('eht');
return (
<>
@@ -67,6 +68,7 @@ function App() {
+
@@ -80,10 +82,13 @@ function App() {
}} />
)}
{chain === 'btc' && (
-
+
)}
{chain === 'sol' && (
-
+
+ )}
+ {chain === 'apt' && (
+
)}
{chain === 'xrp' && (
diff --git a/src/components/Aptos.jsx b/src/components/Aptos.jsx
new file mode 100644
index 0000000..b4c0cd3
--- /dev/null
+++ b/src/components/Aptos.jsx
@@ -0,0 +1,245 @@
+import PropTypes from "prop-types";
+
+import { useWalletSelector } from "@near-wallet-selector/react-hook";
+import { useEffect, useState } from "react";
+import { useDebounce } from "../hooks/debounce";
+import { SIGNET_CONTRACT } from "../config";
+import { chainAdapters } from "chainsig.js";
+import { bigIntToDecimal } from "../utils/bigIntToDecimal";
+import { decimalToBigInt } from "../utils/decimalToBigInt";
+import { Aptos as AptosClient, AptosConfig, Network } from '@aptos-labs/ts-sdk'
+
+const aptosClient = new AptosClient(
+ new AptosConfig({
+ network: Network.TESTNET,
+ })
+)
+
+const Aptos = new chainAdapters.aptos.Aptos({
+ client: aptosClient,
+ contract: SIGNET_CONTRACT,
+})
+
+export function AptosView({ props: { setStatus } }) {
+ const { signedAccountId, signAndSendTransactions } = useWalletSelector();
+
+ const [receiver, setReceiver] = useState("0x3b0c3efaa16f5c7c53d3ca9c12622c90542ff36485f7f713ba8e76756a3fbbea");
+ const [amount, setAmount] = useState(1);
+ const [loading, setLoading] = useState(false);
+ const [step, setStep] = useState("request");
+ const [signedTransaction, setSignedTransaction] = useState(null);
+ const [senderAddress, setSenderAddress] = useState("");
+ const [senderPK, setSenderPK] = useState("");
+
+ const [derivation, setDerivation] = useState("aptos-1");
+ const derivationPath = useDebounce(derivation, 500);
+
+ useEffect(() => {
+ setSenderAddress("Waiting for you to stop typing...");
+ }, [derivation]);
+
+ useEffect(() => {
+ setAptosAddress();
+
+ async function setAptosAddress() {
+ setStatus("Querying your address and balance");
+ setSenderAddress(`Deriving address from path ${derivationPath}...`);
+
+ const { address,publicKey } = await Aptos.deriveAddressAndPublicKey(signedAccountId, derivationPath);
+
+ setSenderAddress(address);
+ setSenderPK(publicKey);
+
+ const balance = await Aptos.getBalance(address);
+
+ setStatus(
+ `Your Aptos address is: ${address}, balance: ${bigIntToDecimal(balance.balance, balance.decimals)} APT`
+ );
+ }
+
+ }, [signedAccountId, derivationPath, setStatus]);
+
+ async function chainSignature() {
+ setStatus("🏗️ Creating transaction");
+
+ const transactionPayload = {
+ function: '0x1::aptos_account::transfer',
+ functionArguments: [
+ receiver,
+ decimalToBigInt(amount, 8),
+ ],
+ };
+
+ const transaction = await aptosClient.transaction.build.simple({
+ sender: senderAddress,
+ data: transactionPayload,
+ })
+
+ const { hashesToSign } = await Aptos.prepareTransactionForSigning(transaction)
+ setStatus(
+ "🕒 Asking MPC to sign the transaction, this might take a while..."
+ );
+
+ try {
+ const rsvSignatures = await SIGNET_CONTRACT.sign({
+ payloads: hashesToSign,
+ path: derivationPath,
+ keyType: "Eddsa",
+ signerAccount: {
+ accountId: signedAccountId,
+ signAndSendTransactions
+ }
+ });
+
+ if (!rsvSignatures[0] || !rsvSignatures[0].signature) {
+ throw new Error("Failed to sign transaction");
+ }
+
+ const txSerialized = Aptos.finalizeTransactionSigning({
+ transaction,
+ rsvSignatures: rsvSignatures[0],
+ publicKey: senderPK
+ });
+
+ setSignedTransaction(txSerialized);
+ setStatus("✅ Signed payload ready to be relayed to the Aptos network");
+ setStep("relay");
+ } catch (e) {
+ console.log(e);
+ setStatus(`❌ Error: ${e.message}`);
+ setLoading(false);
+ }
+ }
+
+ async function relayTransaction() {
+ setLoading(true);
+ setStatus(
+ "🔗 Relaying transaction to the Aptos network..."
+ );
+
+ try {
+ const txHash = await Aptos.broadcastTx(signedTransaction);
+
+ setStatus(
+ <>
+
+ {" "}
+ ✅ Successfully Broadcasted{" "}
+
+ >
+ );
+ } catch (e) {
+ if (e.message.includes("TRANSACTION_EXPIRED")) {
+ setStatus("⏰ Transaction expired, creating a new one...");
+ setStep("request");
+ setLoading(false);
+ return;
+ }
+ setStatus(`❌ Error: ${e.message}`);
+ }
+
+ setStep("request");
+ setLoading(false);
+ }
+
+ const UIChainSignature = async () => {
+ setLoading(true);
+ await chainSignature();
+ setLoading(false);
+ };
+
+ return (<>
+
+
+
+
+
setDerivation(e.target.value)}
+ disabled={loading}
+ />
+
+ {" "}
+ {senderAddress}{" "}
+
+
+
+
+
+
+ setReceiver(e.target.value)}
+ disabled={loading}
+ />
+
+
+
+
+
+
setAmount(e.target.value)}
+ step="0.1"
+ min="0"
+ disabled={loading}
+ />
+
APT units
+
+
+
+
+ {step === "request" && (
+
+ )}
+ {step === "relay" && (
+
+ )}
+
+ >)
+}
+
+AptosView.propTypes = {
+ props: PropTypes.shape({
+ setStatus: PropTypes.func.isRequired,
+ }).isRequired,
+};