Skip to content

Commit

Permalink
feat(multisig): Added notification after broadcast + check on expirat…
Browse files Browse the repository at this point in the history
…ion date
  • Loading branch information
tshiuan committed May 1, 2023
1 parent 0a96fa8 commit 52d3620
Show file tree
Hide file tree
Showing 7 changed files with 235 additions and 76 deletions.
235 changes: 161 additions & 74 deletions my-app/src/App.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { Client } from "@hiveio/dhive";
import React, { useEffect, useState } from "react";
import { io } from "socket.io-client";
import "./App.css";
Expand All @@ -13,12 +14,12 @@ const getVoteTransaction = () => {
extensions: [],
operations: [
[
"vote",
"transfer",
{
voter: "cedric.tests",
author: "\tcedricguillas",
permlink: "introducing-my-new-witness",
weight: 10000,
from: "cedric.tests",
to: "tshiuan89",
amount: "0.001 HIVE",
memo: "",
},
],
],
Expand All @@ -28,6 +29,7 @@ const getVoteTransaction = () => {
};

const socket = io.connect("http://localhost:5001");
const client = new Client("https://api.deathwing.me");

const App = () => {
const [isConnected, setIsConnected] = useState(socket.connected);
Expand All @@ -36,6 +38,7 @@ const App = () => {
const [keychainDetected, setKeychainDetected] = useState(false);
const [usedPubKey, setUsedPubKey] = useState({});
const [signatureRequest, setSignatureRequest] = useState();
const [pendingSignatureRequests, setPendingSignatureRequests] = useState([]);

const checkKeychain = () => {
console.log("check keychain");
Expand All @@ -44,14 +47,18 @@ const App = () => {

useEffect(() => {
if (isConnected) return;
console.log("hello", socket.connected);
checkKeychain();

socket.on("connect", () => {
setSocketIoId(socket.id);
setIsConnected(true);
});

socket.on("transaction_broadcasted_notification", (signatureRequest) => {
console.log(signatureRequest, "was broadcasted");
alert(`signature request ${signatureRequest.id} was broadcasted`);
});

socket.on("disconnect", () => {
setIsConnected(false);
});
Expand All @@ -74,45 +81,49 @@ const App = () => {
(s) => s.publicKey === usedPubKey.key
);

const totalWeight = signatureRequest.signers.reduce((total, signer) => {
return total + signer.weight;
}, 0);
console.log(totalWeight);
// Lock request on backend to be able to broadcast
socket.emit("request_lock", signatureRequest.id, (response) => {
console.log(response);
if (response) {
} else {
console.log("already locked");
window.hive_keychain.requestVerifyKey(
usedPubKey.username,
signer.encryptedTransaction,
signatureRequest.keyType,
(response) => {
const transaction = JSON.parse(response.result.replace("#", ""));
window.hive_keychain.requestSignTx(
usedPubKey.username,
transaction,
signatureRequest.keyType,
(res) => {
const signedTransaction = res.result;
console.log(signedTransaction);
socket.emit(
"sign_transaction",
{
signature:
signedTransaction.signatures[
signedTransaction.signatures.length - 1
],
signerId: signer.id,
signatureRequestId: signatureRequest.id,
},
async (signatures) => {
// Broadcast
console.log("should broadcast", signatures);
transaction.signatures = signatures;
// await client.broadcast.send(transaction);
socket.emit(
"notify_transaction_broadcasted",
{ signatureRequestId: signatureRequest.id },
() => {
console.log("backend notified of broadcast");
}
);
}
);
}
);
}
});
);

let shouldBroadcast = false;
if (totalWeight + signer.weight >= signatureRequest.threshold) {
window.hive_keychain.requestVerifyKey(
usedPubKey.username,
signer.encryptedTransaction,
signatureRequest.keyType,
(response) => {
console.log(response);
window.hive_keychain.requestSignTx(
usedPubKey.username,
JSON.parse(response.result.replace("#", "")),
signatureRequest.keyType,
(res) => {
console.log(res);
const signedTransaction = res.result;
if (shouldBroadcast) {
// broadcast signed transaction
// notifiy backend
} else {
// return signature to backend
}
}
);
}
);
}
// Lock request on backend to be able to broadcast
}, [signatureRequest]);

const sendPing = () => {
Expand All @@ -125,26 +136,75 @@ const App = () => {
}
};

const sendSignerConnectMessage = (username, publicKey) => {
socket.emit("signer_connect", [publicKey], (pendingSignatureRequests) => {
console.log("pending signature requests", pendingSignatureRequests);
});
setUsedPubKey({ username: username, key: publicKey });
const sendSignerConnectMessage = (username) => {
window.hive_keychain.requestSignBuffer(
username,
username,
"posting",
(signBufferResponse) => {
if (signBufferResponse.error) {
console.log("error while signing buffer");
return;
} else {
console.log(signBufferResponse);
socket.emit(
"signer_connect",
[
{
publicKey: signBufferResponse.publicKey,
message: signBufferResponse.result,
username: signBufferResponse.data.username,
},
],
(loginResponse) => {
if (loginResponse.error) {
console.log("login rejected");
} else {
console.log("pending signature requests", loginResponse.result);
setPendingSignatureRequests(loginResponse[username]);
setUsedPubKey({
username: username,
key: signBufferResponse.publicKey,
});
}
}
);
}
}
);
};

const sendRequestSignatureMessage = (encodedTransaction) => {
socket.emit("request_signature", {
expirationDate: getVoteTransaction().expiration,
threshold: 2,
keyType: "Posting",
signers: [
{
encryptedTransaction: encodedTransaction,
publicKey: cedric3PubKey,
const sendRequestSignatureMessage = (
encodedTransaction,
signature,
username
) => {
socket.emit(
"request_signature",
{
signatureRequest: {
expirationDate: getVoteTransaction().expiration,
threshold: 2,
keyType: "Posting",
signers: [
{
encryptedTransaction: encodedTransaction,
publicKey: cedric3PubKey,
weight: 1,
},
],
},
initialSigner: {
publicKey: cedric2PubKey,
signature: signature,
username: username,
weight: 1,
},
],
});
},
() => {
console.log("signature requested");
}
);
};

const initMultisigTransaction = () => {
Expand All @@ -153,22 +213,33 @@ const App = () => {
getVoteTransaction(),
"Posting",
(response) => {
if (response.result) {
const signedTransaction = response.result;
if (signedTransaction) {
// Retrieve other signers public key
window.hive_keychain.requestEncodeMessage(
"cedric.tests2",
"cedric.tests3",
`#${JSON.stringify(response.result)}`,
"Posting",
(res) => {
sendRequestSignatureMessage(res.result);
if (res.result) {
sendRequestSignatureMessage(
res.result,
signedTransaction.signatures[0],
"cedric.tests2"
);
}
}
);
}
}
);
};

const signPending = (p) => {
console.log(p);
};

return (
<div className="App">
<div>
Expand All @@ -180,19 +251,35 @@ const App = () => {
</div>
<button onClick={sendPing}>Send Ping</button>
<br />
<button
onClick={() => sendSignerConnectMessage("cedric.tests2", cedric2PubKey)}
>
Send connect message cedric.tests2
</button>
<button
onClick={() => sendSignerConnectMessage("cedric.tests3", cedric3PubKey)}
>
Send connect message cedric.tests3
</button>
<button onClick={() => initMultisigTransaction()}>
Initialize transaction (with cedric2)
</button>
{navigator.userAgentData.brands.some((b) =>
b.brand.includes("Brave")
) && (
<>
<button onClick={() => sendSignerConnectMessage("cedric.tests2")}>
Send connect message cedric.tests2
</button>
<button onClick={() => initMultisigTransaction()}>
Initialize transaction (with cedric2)
</button>
</>
)}
{!navigator.userAgentData.brands.some((b) =>
b.brand.includes("Brave")
) && (
<button onClick={() => sendSignerConnectMessage("cedric.tests3")}>
Send connect message cedric.tests3
</button>
)}
<br /> <br /> <br /> <br />
{/* {pendingSignatureRequests.length > 0 && (
<div style={{ display: "flex", flexDirection: "row", rowGap: 8 }}>
{pendingSignatureRequests.map((p, i) => (
<div key={i}>
signature {i} <button onClick={signPending(p)}></button>
</div>
))}
</div>
)} */}
</div>
);
};
Expand Down
26 changes: 25 additions & 1 deletion src/signature-request/signature-request.logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import { SignatureRequestRepository } from "./signature-request.repository";
import { Signer } from "./signer/signer.entity";
import { SignerRepository } from "./signer/signer.repository";

const getById = async (signatureRequestId: SignatureRequest["id"]) => {
return SignatureRequestRepository.findById(signatureRequestId);
};

const requestSignature = async (
threshold: number,
expirationDate: Date,
Expand Down Expand Up @@ -51,7 +55,8 @@ const requestLock = async (requestId: number) => {
};

const retrieveAllPending = async (publicKeys: string) => {
const allSignatureRequest = await SignatureRequestRepository.findAll();
const allSignatureRequest = await SignatureRequestRepository.findAllPending();
console.log(allSignatureRequest);
const requestsToSign: SignatureRequest[] = [];
for (const request of allSignatureRequest) {
for (const potentialSigner of request.signers) {
Expand Down Expand Up @@ -89,11 +94,30 @@ const getSignatureIfCanBroadcast = async (signatureRequestId: number) => {
}
};

const setAsBroadcasted = async (signatureRequestId: SignatureRequest["id"]) => {
await SignatureRequestRepository.setAsBroadcasted(signatureRequestId);
};

const getAllSigners = async (signatureRequestId: SignatureRequest["id"]) => {
const signatureRequest = await SignatureRequestRepository.findById(
signatureRequestId
);
return signatureRequest.signers.filter((signer) => !!signer.signature);
};

const setSignerAsNotified = async (signerId: number) => {
await SignerRepository.setAsNotified(signerId);
};

export const SignatureRequestLogic = {
requestSignature,
requestLock,
retrieveAllPending,
saveSignature,
refuseTransaction,
getSignatureIfCanBroadcast,
setAsBroadcasted,
getAllSigners,
getById,
setSignerAsNotified,
};
Loading

0 comments on commit 52d3620

Please sign in to comment.