This commit is contained in:
SvyatoslavArtymovych 2023-06-19 15:34:42 +03:00
parent 68afa7c863
commit 4e97040d00
10 changed files with 1264 additions and 2300 deletions

File diff suppressed because one or more lines are too long

View File

@ -5,75 +5,6 @@
* Copyright (c) 2013, salesforce.com
*/
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
/**
* Checks if an event is supported in the current execution environment.
*
* NOTE: This will not work correctly for non-generic events such as `change`,
* `reset`, `load`, `error`, and `select`.
*
* Borrows from Modernizr.
*
* @param {string} eventNameSuffix Event name, e.g. "click".
* @return {boolean} True if the event is supported.
* @internal
* @license Modernizr 3.0.0pre (Custom Build) | MIT
*/
/**
* @license React
* react-dom.development.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* react.development.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* @license React
* scheduler.development.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**
* [js-sha3]{@link https://github.com/emn178/js-sha3}
*
@ -83,15 +14,6 @@
* @license MIT
*/
/** @license React v16.13.1
* react-is.development.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/**!
* Sortable 1.15.0
* @author RubaXa <trash@rubaxa.org>

View File

@ -85,7 +85,7 @@ def verify():
try:
siwe_message.verify(
body["message"]["signature"],
body["signature"],
provider=HTTPProvider(current_app.config["HTTP_PROVIDER_URL"]),
)

View File

@ -13,7 +13,6 @@
"author": "",
"license": "ISC",
"dependencies": {
"@metamask/sdk": "^0.3.2",
"@types/lodash.debounce": "^4.0.7",
"@types/sortablejs": "^1.15.1",
"ethers": "5.5.3",

2365
poetry.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -15,10 +15,10 @@ click = "^8.1.3"
email-validator = "^1.3.1"
psycopg2-binary = "^2.9.5"
pydantic = "^1.10.7"
siwe = "^2.2.0"
flask-admin = "^1.6.1"
wtforms = "^3.0.1"
flask-wtf = "^1.1.1"
siwe = "^2.2.0"
[tool.poetry.dev-dependencies]
pytest = "^7.1.1"

View File

@ -1,97 +0,0 @@
import {ethers} from 'ethers';
import {SiweMessage} from 'siwe';
import MetaMaskSDK from '@metamask/sdk';
import {hexlify} from '@ethersproject/bytes';
import {toUtf8Bytes} from '@ethersproject/strings';
export function initWallet() {
// current page url
const domain = window.location.host;
// protocol, hostname and port number of the URL
const origin = window.location.origin;
// connect to ethereum network and sign transactions with Metamask
async function signInWithEthereum() {
// if (!window.hasOwnProperty('ethereum')) {
// let result = confirm(
// "You don't have needed extension! Do you want to install it?",
// );
// localStorage.setItem('showExtensionAlert', 'false');
// if (result) {
// window.open('https://metamask.io/', '_blank');
// }
// return;
// }
// if (!window.hasOwnProperty('ethereum')) {
// console.error('Required extension not found');
// return;
// }
const options = {
injectProvider: false,
communicationLayerPreference: 'webrtc',
};
const MMSDK = new MetaMaskSDK(options);
const ethereum = MMSDK.getProvider();
// create siwe message and call backend to get a nonce
const res1 = await fetch('/nonce', {
credentials: 'include',
});
const text = await res1.text();
const response = await ethereum.send('eth_requestAccounts', []); // <- this promps user to connect metamask
const address = ethers.utils.getAddress(response.result[0]);
const message = new SiweMessage({
domain: domain,
address: address,
statement: 'Sign in with Ethereum to the app.',
uri: origin,
version: '1',
chainId: '1',
nonce: text,
});
const siweSign = async message => {
try {
const from = address;
const msg = message.signMessage();
const data = typeof msg === 'string' ? toUtf8Bytes(msg) : msg;
const hex = hexlify(data);
const sign = await ethereum.request({
method: 'personal_sign',
params: [hex, from],
});
debugger;
return sign;
} catch (err) {
console.error(err);
}
};
const sign = await siweSign(message);
message.signature = sign;
// post message and signature to backend where it will be verified
const res2 = await fetch(`/verify`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({message, message}),
credentials: 'include',
redirect: 'follow',
});
if (res2.status == 200) {
window.location.replace(res2.url);
} else window.location.reload();
}
const connectWalletBtns = document.querySelectorAll('#connectWalletBtn');
if (connectWalletBtns) {
connectWalletBtns.forEach(btn =>
btn.addEventListener('click', () => {
signInWithEthereum();
}),
);
}
}

76
src/wallet.ts Normal file
View File

@ -0,0 +1,76 @@
import {ethers} from 'ethers';
import {SiweMessage} from 'siwe';
interface IEthereumOwner extends Window {
ethereum:
| ethers.providers.ExternalProvider
| ethers.providers.JsonRpcFetchFunc;
}
export function initWallet() {
// current page url
const domain = window.location.host;
// protocol, hostname and port number of the URL
const origin = window.location.origin;
// connect to ethereum network and sign transactions with Metamask
async function signInWithEthereum() {
if (!window.hasOwnProperty('ethereum')) {
let result = confirm(
"You don't have needed extension! Do you want to install it?",
);
localStorage.setItem('showExtensionAlert', 'false');
if (result) {
window.open('https://metamask.io/', '_blank');
}
return;
}
if (!window.hasOwnProperty('ethereum')) {
console.error('Required extension not found');
return;
}
const eOwner: IEthereumOwner = window as any;
const provider = new ethers.providers.Web3Provider(eOwner.ethereum);
const signer = provider.getSigner();
// create siwe message and call backend to get a nonce
const res1 = await fetch('/nonce', {
credentials: 'include',
});
await provider.send('eth_requestAccounts', []); // <- this promps user to connect metamask
const message = new SiweMessage({
domain: domain,
address: await signer.getAddress(),
statement: 'Sign in with Ethereum to the app.',
uri: origin,
version: '1',
chainId: '1',
nonce: await res1.text(),
});
const signature = await signer.signMessage(message.signMessage());
message.signature = signature;
// post message and signature to backend where it will be verified
const res2 = await fetch(`/verify`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({message, signature}),
credentials: 'include',
redirect: 'follow',
});
if (res2.status == 200) {
window.location.replace(res2.url);
} else window.location.reload();
}
const connectWalletBtns = document.querySelectorAll('#connectWalletBtn');
if (connectWalletBtns) {
connectWalletBtns.forEach(btn =>
btn.addEventListener('click', () => {
signInWithEthereum();
}),
);
}
}

View File

@ -12,6 +12,6 @@
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
},
"include": ["src/**/*.ts*", "src/wallet.js"],
"include": ["src/**/*.ts*"],
"exclude": ["node_modules", "dist", "lib"]
}

939
yarn.lock

File diff suppressed because it is too large Load Diff