Skip to content

Commit

Permalink
feat(ui): update packages and improve UX/UI
Browse files Browse the repository at this point in the history
  • Loading branch information
matiasbenary committed Dec 21, 2024
1 parent 99c04f7 commit 8ab6f88
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 32 deletions.
34 changes: 25 additions & 9 deletions frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,38 @@
"lint": "next lint"
},
"dependencies": {
"@near-wallet-selector/core": "^8.9.11",
"@near-wallet-selector/here-wallet": "^8.9.11",
"@near-wallet-selector/modal-ui": "^8.9.11",
"@near-wallet-selector/my-near-wallet": "^8.9.11",
"@near-js/providers": "^1.0.1",
"@near-wallet-selector/bitte-wallet": "^8.9.14",
"@near-wallet-selector/core": "^8.9.14",
"@near-wallet-selector/ethereum-wallets": "^8.9.14",
"@near-wallet-selector/here-wallet": "^8.9.14",
"@near-wallet-selector/ledger": "^8.9.14",
"@near-wallet-selector/meteor-wallet": "^8.9.14",
"@near-wallet-selector/modal-ui": "^8.9.14",
"@near-wallet-selector/my-near-wallet": "^8.9.14",
"@near-wallet-selector/near-mobile-wallet": "^8.9.14",
"@near-wallet-selector/sender": "^8.9.14",
"@near-wallet-selector/welldone-wallet": "^8.9.14",
"@web3modal/wagmi": "^5.1.11",
"bootstrap": "^5",
"bootstrap-icons": "^1.11.3",
"near-api-js": "^4.0.3",
"next": "14.2.3",
"near-api-js": "^5.0.1",
"next": "14.2.5",
"react": "^18",
"react-dom": "^18"
"react-dom": "^18",
"wagmi": "^2.13.3"
},
"overrides": {
"@near-wallet-selector/ethereum-wallets": {
"near-api-js": "4.0.3"
}
},
"resolutions": {
"near-api-js": "4.0.3"
},
},
"devDependencies": {
"eslint": "^8",
"encoding": "^0.1.13",
"eslint": "^9",
"eslint-config-next": "14.2.3"
}
}
20 changes: 20 additions & 0 deletions frontend/src/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,23 @@ const contractPerNetwork = {

export const NetworkId = "testnet";
export const CoinFlipContract = contractPerNetwork[NetworkId];

// Chains for EVM Wallets
const evmWalletChains = {
mainnet: {
chainId: 397,
name: 'Near Mainnet',
explorer: 'https://eth-explorer.near.org',
rpc: 'https://eth-rpc.mainnet.near.org',
},
testnet: {
chainId: 398,
name: 'Near Testnet',
explorer: 'https://eth-explorer-testnet.near.org',
rpc: 'https://eth-rpc.testnet.near.org',
},
};


export const EVMWalletChain = evmWalletChains[NetworkId];

10 changes: 9 additions & 1 deletion frontend/src/pages/_app.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@ import { Navigation } from '@/components/Navigation';
import { Wallet } from '@/wallets/near';
import { NetworkId, CoinFlipContract } from '@/config';

const wallet = new Wallet({ createAccessKeyFor: CoinFlipContract, networkId: NetworkId });
// Wallet instance
// const wallet = new Wallet({ networkId: NetworkId });

// Optional: Create an access key so the user does not need to sign transactions. Read more about access keys here: https://docs.near.org/concepts/protocol/access-keys
const wallet = new Wallet({
createAccessKeyFor: CoinFlipContract,
networkId: NetworkId,
});


export default function MyApp({ Component, pageProps }) {
const [signedAccountId, setSignedAccountId] = useState('');
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/pages/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ export default function Home() {

if (guess === outcome) {
setStatus("You were right, you won a point!");
setPoints(points+1);
} else {
setStatus("You were wrong, you lost a point");
setPoints(points ? points - 1 : 0);
}

updateScore();
};

const updateScore = async () => {
Expand Down
126 changes: 106 additions & 20 deletions frontend/src/wallets/near.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
// near api js
import { providers } from 'near-api-js';

// wallet selector
import { distinctUntilChanged, map } from 'rxjs';
import '@near-wallet-selector/modal-ui/styles.css';
import { setupModal } from '@near-wallet-selector/modal-ui';

import { setupBitteWallet } from '@near-wallet-selector/bitte-wallet';
import { setupWalletSelector } from '@near-wallet-selector/core';
import { setupHereWallet } from '@near-wallet-selector/here-wallet';
import { setupEthereumWallets } from '@near-wallet-selector/ethereum-wallets';
import { setupLedger } from '@near-wallet-selector/ledger';
import { setupMeteorWallet } from '@near-wallet-selector/meteor-wallet';
import { setupModal } from '@near-wallet-selector/modal-ui';
import { setupMyNearWallet } from '@near-wallet-selector/my-near-wallet';
import { setupSender } from '@near-wallet-selector/sender';
import { setupHereWallet } from '@near-wallet-selector/here-wallet';
import { setupNearMobileWallet } from '@near-wallet-selector/near-mobile-wallet';
import { setupWelldoneWallet } from '@near-wallet-selector/welldone-wallet';


// near api js
import { providers, utils } from 'near-api-js';
import { createContext } from 'react';

// ethereum wallets
import { wagmiConfig, web3Modal } from '@/wallets/web3modal';

const THIRTY_TGAS = '30000000000000';
const NO_DEPOSIT = '0';
Expand All @@ -30,27 +42,32 @@ export class Wallet {
/**
* To be called when the website loads
* @param {Function} accountChangeHook - a function that is called when the user signs in or out#
* @returns {Promise<string>} - the accountId of the signed-in user
* @returns {Promise<string>} - the accountId of the signed-in user
*/
startUp = async (accountChangeHook) => {
this.selector = setupWalletSelector({
network: this.networkId,
modules: [setupMyNearWallet(), setupHereWallet()]
modules: [
setupMeteorWallet(),
setupEthereumWallets({ wagmiConfig, web3Modal, alwaysOnboardDuringSignIn: true }),
setupLedger(),
setupBitteWallet(),
setupHereWallet(),
setupSender(),
setupNearMobileWallet(),
setupWelldoneWallet(),
setupMyNearWallet(),
],
});

const walletSelector = await this.selector;
const isSignedIn = walletSelector.isSignedIn();
const accountId = isSignedIn ? walletSelector.store.getState().accounts[0].accountId : '';

walletSelector.store.observable
.pipe(
map(state => state.accounts),
distinctUntilChanged()
)
.subscribe(accounts => {
const signedAccount = accounts.find((account) => account.active)?.accountId;
accountChangeHook(signedAccount);
});
walletSelector.store.observable.subscribe(async (state) => {
const signedAccount = state?.accounts.find((account) => account.active)?.accountId;
accountChangeHook(signedAccount || '');
});

return accountId;
};
Expand Down Expand Up @@ -83,7 +100,7 @@ export class Wallet {
const url = `https://rpc.${this.networkId}.near.org`;
const provider = new providers.JsonRpcProvider({ url });

let res = await provider.query({
const res = await provider.query({
request_type: 'call_function',
account_id: contractId,
method_name: method,
Expand All @@ -93,7 +110,6 @@ export class Wallet {
return JSON.parse(Buffer.from(res.result).toString());
};


/**
* Makes a call to a contract
* @param {Object} options - the options for the call
Expand Down Expand Up @@ -126,7 +142,7 @@ export class Wallet {
};

/**
* Retrieves transaction result from the network
* Makes a call to a contract
* @param {string} txhash - the transaction hash
* @returns {Promise<JSON.value>} - the result of the transaction
*/
Expand All @@ -135,7 +151,77 @@ export class Wallet {
const { network } = walletSelector.options;
const provider = new providers.JsonRpcProvider({ url: network.nodeUrl });

// Retrieve transaction result from the network
const transaction = await provider.txStatus(txhash, 'unnused');
return providers.getTransactionLastResult(transaction);
};

/**
* Gets the balance of an account
* @param {string} accountId - the account id to get the balance of
* @param {boolean} format - whether to format the balance
* @returns {Promise<number>} - the balance of the account
*
*/
getBalance = async (accountId, format = false) => {
const walletSelector = await this.selector;
const { network } = walletSelector.options;
const provider = new providers.JsonRpcProvider({ url: network.nodeUrl });

// Retrieve account state from the network
const account = await provider.query({
request_type: 'view_account',
account_id: accountId,
finality: 'final',
});

// Format the amount if needed
if (format) {
return account.amount ? utils.format.formatNearAmount(account.amount) : '0';
} else {
return account.amount || '0';
}
};

/**
* Signs and sends transactions
* @param {Object[]} transactions - the transactions to sign and send
* @returns {Promise<Transaction[]>} - the resulting transactions
*
*/
signAndSendTransactions = async ({ transactions }) => {
const selectedWallet = await (await this.selector).wallet();
return selectedWallet.signAndSendTransactions({ transactions });
};

/**
*
* @param {string} accountId
* @returns {Promise<Object[]>} - the access keys for the
*/
getAccessKeys = async (accountId) => {
const walletSelector = await this.selector;
const { network } = walletSelector.options;
const provider = new providers.JsonRpcProvider({ url: network.nodeUrl });

// Retrieve account state from the network
const keys = await provider.query({
request_type: 'view_access_key_list',
account_id: accountId,
finality: 'final',
});
return keys.keys;
};
}

/**
* @typedef NearContext
* @property {import('./wallets/near').Wallet} wallet Current wallet
* @property {string} signedAccountId The AccountId of the signed user
*/

/** @type {import ('react').Context<NearContext>} */
export const NearContext = createContext({
wallet: undefined,
signedAccountId: '',
});
42 changes: 42 additions & 0 deletions frontend/src/wallets/web3modal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { injected,walletConnect } from '@wagmi/connectors';
import { createConfig,http, reconnect } from '@wagmi/core';
import { createWeb3Modal } from '@web3modal/wagmi';

import { EVMWalletChain,NetworkId } from '@/config';

// Config
const near = {
id: EVMWalletChain.chainId,
name: EVMWalletChain.name,
nativeCurrency: {
decimals: 18,
name: 'NEAR',
symbol: 'NEAR',
},
rpcUrls: {
default: { http: [EVMWalletChain.rpc] },
public: { http: [EVMWalletChain.rpc] },
},
blockExplorers: {
default: {
name: 'NEAR Explorer',
url: EVMWalletChain.explorer,
},
},
testnet: NetworkId === 'testnet',
};

// Get your projectId at https://cloud.reown.com
const projectId = '5bb0fe33763b3bea40b8d69e4269b4ae';

export const wagmiConfig = createConfig({
chains: [near],
transports: { [near.id]: http() },
connectors: [walletConnect({ projectId, showQrModal: false }), injected({ shimDisconnect: true })],
});

// Preserve login state on page reload
reconnect(wagmiConfig);

// Modal for login
export const web3Modal = createWeb3Modal({ wagmiConfig, projectId });

0 comments on commit 8ab6f88

Please sign in to comment.